summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@src.gnome.org>2009-03-16 11:43:23 +0000
committerAlexander Larsson <alexl@src.gnome.org>2009-03-16 11:43:23 +0000
commit4ad537c5c3e17e1efe289020d7dc6cd0efae42c5 (patch)
tree891f2ec720f5ae321762965a00d352ad0a1592a2
parent4c59b80ab2b0e942bd45ff12f238038293d21821 (diff)
downloadgvfs-GVFS_1_2_0.tar.gz
Tagged for release 1.2.0GVFS_1_2_0
svn path=/tags/GVFS_1_2_0/; revision=2331
-rw-r--r--trunk/.gitignore33
-rw-r--r--trunk/AUTHORS65
-rw-r--r--trunk/COPYING482
-rw-r--r--trunk/CVSVERSION0
-rw-r--r--trunk/ChangeLog6553
-rw-r--r--trunk/INSTALL3
-rw-r--r--trunk/MAINTAINERS8
-rw-r--r--trunk/Makefile.am24
-rw-r--r--trunk/NEWS360
-rw-r--r--trunk/README21
-rw-r--r--trunk/TODO32
-rwxr-xr-xtrunk/autogen.sh126
-rw-r--r--trunk/client/.gitignore1
-rw-r--r--trunk/client/Makefile.am82
-rw-r--r--trunk/client/gdaemonfile.c2805
-rw-r--r--trunk/client/gdaemonfile.h54
-rw-r--r--trunk/client/gdaemonfileenumerator.c461
-rw-r--r--trunk/client/gdaemonfileenumerator.h57
-rw-r--r--trunk/client/gdaemonfileinputstream.c2118
-rw-r--r--trunk/client/gdaemonfileinputstream.h52
-rw-r--r--trunk/client/gdaemonfilemonitor.c216
-rw-r--r--trunk/client/gdaemonfilemonitor.h52
-rw-r--r--trunk/client/gdaemonfileoutputstream.c1647
-rw-r--r--trunk/client/gdaemonfileoutputstream.h53
-rw-r--r--trunk/client/gdaemonmount.c278
-rw-r--r--trunk/client/gdaemonmount.h57
-rw-r--r--trunk/client/gdaemonvfs.c1152
-rw-r--r--trunk/client/gdaemonvfs.h75
-rw-r--r--trunk/client/gdaemonvolumemonitor.c321
-rw-r--r--trunk/client/gdaemonvolumemonitor.h60
-rw-r--r--trunk/client/gvfsdaemondbus.c1023
-rw-r--r--trunk/client/gvfsdaemondbus.h80
-rw-r--r--trunk/client/gvfsfusedaemon.c2324
-rw-r--r--trunk/client/gvfsiconloadable.c431
-rw-r--r--trunk/client/gvfsiconloadable.h35
-rw-r--r--trunk/client/gvfsurimapper.c220
-rw-r--r--trunk/client/gvfsurimapper.h109
-rw-r--r--trunk/client/gvfsuriutils.c291
-rw-r--r--trunk/client/gvfsuriutils.h49
-rw-r--r--trunk/client/httpuri.c294
-rw-r--r--trunk/client/smburi.c297
-rw-r--r--trunk/client/test-uri-utils.c60
-rw-r--r--trunk/common/Makefile.am47
-rw-r--r--trunk/common/gdbusutils.c1334
-rw-r--r--trunk/common/gdbusutils.h95
-rw-r--r--trunk/common/gmountoperationdbus.c324
-rw-r--r--trunk/common/gmountoperationdbus.h40
-rw-r--r--trunk/common/gmountsource.c716
-rw-r--r--trunk/common/gmountsource.h115
-rw-r--r--trunk/common/gmountspec.c637
-rw-r--r--trunk/common/gmountspec.h109
-rw-r--r--trunk/common/gmounttracker.c634
-rw-r--r--trunk/common/gmounttracker.h87
-rw-r--r--trunk/common/gsysutils.c181
-rw-r--r--trunk/common/gsysutils.h39
-rw-r--r--trunk/common/gvfsdaemonprotocol.c553
-rw-r--r--trunk/common/gvfsdaemonprotocol.h194
-rw-r--r--trunk/common/gvfsdnssdresolver.c1269
-rw-r--r--trunk/common/gvfsdnssdresolver.h80
-rw-r--r--trunk/common/gvfsdnssdutils.c323
-rw-r--r--trunk/common/gvfsdnssdutils.h50
-rw-r--r--trunk/common/gvfsfileinfo.c278
-rw-r--r--trunk/common/gvfsfileinfo.h37
-rw-r--r--trunk/common/gvfsicon.c282
-rw-r--r--trunk/common/gvfsicon.h69
-rw-r--r--trunk/common/gvfsmountinfo.c737
-rw-r--r--trunk/common/gvfsmountinfo.h52
-rw-r--r--trunk/configure.ac585
-rw-r--r--trunk/daemon/.gitignore16
-rw-r--r--trunk/daemon/Makefile.am414
-rw-r--r--trunk/daemon/ParseFTPList.c1842
-rw-r--r--trunk/daemon/ParseFTPList.h127
-rw-r--r--trunk/daemon/archive.mount.in5
-rw-r--r--trunk/daemon/burn.mount.in5
-rw-r--r--trunk/daemon/cdda.mount.in4
-rw-r--r--trunk/daemon/computer.mount.in5
-rw-r--r--trunk/daemon/daemon-main-generic.c59
-rw-r--r--trunk/daemon/daemon-main.c296
-rw-r--r--trunk/daemon/daemon-main.h45
-rw-r--r--trunk/daemon/dav+sd.mount.in4
-rw-r--r--trunk/daemon/dav.mount.in4
-rw-r--r--trunk/daemon/dbus-gmain.c717
-rw-r--r--trunk/daemon/dbus-gmain.h63
-rw-r--r--trunk/daemon/dns-sd.mount.in4
-rw-r--r--trunk/daemon/ftp.mount.in7
-rw-r--r--trunk/daemon/gphoto2.mount.in4
-rw-r--r--trunk/daemon/gvfs-daemon.service.in3
-rw-r--r--trunk/daemon/gvfsbackend.c677
-rw-r--r--trunk/daemon/gvfsbackend.h463
-rw-r--r--trunk/daemon/gvfsbackendarchive.c793
-rw-r--r--trunk/daemon/gvfsbackendarchive.h50
-rw-r--r--trunk/daemon/gvfsbackendburn.c1047
-rw-r--r--trunk/daemon/gvfsbackendburn.h50
-rw-r--r--trunk/daemon/gvfsbackendcdda.c1035
-rw-r--r--trunk/daemon/gvfsbackendcdda.h54
-rw-r--r--trunk/daemon/gvfsbackendcomputer.c1125
-rw-r--r--trunk/daemon/gvfsbackendcomputer.h50
-rw-r--r--trunk/daemon/gvfsbackenddav.c2335
-rw-r--r--trunk/daemon/gvfsbackenddav.h50
-rw-r--r--trunk/daemon/gvfsbackenddnssd.c800
-rw-r--r--trunk/daemon/gvfsbackenddnssd.h50
-rw-r--r--trunk/daemon/gvfsbackendftp.c2573
-rw-r--r--trunk/daemon/gvfsbackendftp.h50
-rw-r--r--trunk/daemon/gvfsbackendgphoto2.c3428
-rw-r--r--trunk/daemon/gvfsbackendgphoto2.h51
-rw-r--r--trunk/daemon/gvfsbackendhttp.c685
-rw-r--r--trunk/daemon/gvfsbackendhttp.h79
-rw-r--r--trunk/daemon/gvfsbackendlocaltest.c1252
-rw-r--r--trunk/daemon/gvfsbackendlocaltest.h94
-rw-r--r--trunk/daemon/gvfsbackendnetwork.c933
-rw-r--r--trunk/daemon/gvfsbackendnetwork.h55
-rw-r--r--trunk/daemon/gvfsbackendobexftp-cap-parser.c595
-rw-r--r--trunk/daemon/gvfsbackendobexftp-cap-parser.h53
-rw-r--r--trunk/daemon/gvfsbackendobexftp-fl-parser.c424
-rw-r--r--trunk/daemon/gvfsbackendobexftp-fl-parser.h37
-rw-r--r--trunk/daemon/gvfsbackendobexftp.c2116
-rw-r--r--trunk/daemon/gvfsbackendobexftp.h50
-rw-r--r--trunk/daemon/gvfsbackendsftp.c4202
-rw-r--r--trunk/daemon/gvfsbackendsftp.h50
-rw-r--r--trunk/daemon/gvfsbackendsmb.c2102
-rw-r--r--trunk/daemon/gvfsbackendsmb.h53
-rw-r--r--trunk/daemon/gvfsbackendsmbbrowse.c1502
-rw-r--r--trunk/daemon/gvfsbackendsmbbrowse.h53
-rw-r--r--trunk/daemon/gvfsbackendtest.c592
-rw-r--r--trunk/daemon/gvfsbackendtest.h56
-rw-r--r--trunk/daemon/gvfsbackendtrash.c872
-rw-r--r--trunk/daemon/gvfsbackendtrash.h25
-rw-r--r--trunk/daemon/gvfschannel.c720
-rw-r--r--trunk/daemon/gvfschannel.h91
-rw-r--r--trunk/daemon/gvfsdaemon.c1060
-rw-r--r--trunk/daemon/gvfsdaemon.h76
-rw-r--r--trunk/daemon/gvfsdaemonutils.c286
-rw-r--r--trunk/daemon/gvfsdaemonutils.h52
-rw-r--r--trunk/daemon/gvfsjob.c327
-rw-r--r--trunk/daemon/gvfsjob.h108
-rw-r--r--trunk/daemon/gvfsjobcloseread.c133
-rw-r--r--trunk/daemon/gvfsjobcloseread.h63
-rw-r--r--trunk/daemon/gvfsjobclosewrite.c141
-rw-r--r--trunk/daemon/gvfsjobclosewrite.h67
-rw-r--r--trunk/daemon/gvfsjobcopy.c211
-rw-r--r--trunk/daemon/gvfsjobcopy.h67
-rw-r--r--trunk/daemon/gvfsjobcreatemonitor.c246
-rw-r--r--trunk/daemon/gvfsjobcreatemonitor.h71
-rw-r--r--trunk/daemon/gvfsjobdbus.c196
-rw-r--r--trunk/daemon/gvfsjobdbus.h70
-rw-r--r--trunk/daemon/gvfsjobdelete.c156
-rw-r--r--trunk/daemon/gvfsjobdelete.h63
-rw-r--r--trunk/daemon/gvfsjobenumerate.c320
-rw-r--r--trunk/daemon/gvfsjobenumerate.h78
-rw-r--r--trunk/daemon/gvfsjobmakedirectory.c156
-rw-r--r--trunk/daemon/gvfsjobmakedirectory.h63
-rw-r--r--trunk/daemon/gvfsjobmakesymlink.c162
-rw-r--r--trunk/daemon/gvfsjobmakesymlink.h64
-rw-r--r--trunk/daemon/gvfsjobmount.c216
-rw-r--r--trunk/daemon/gvfsjobmount.h68
-rw-r--r--trunk/daemon/gvfsjobmountmountable.c216
-rw-r--r--trunk/daemon/gvfsjobmountmountable.h76
-rw-r--r--trunk/daemon/gvfsjobmove.c210
-rw-r--r--trunk/daemon/gvfsjobmove.h71
-rw-r--r--trunk/daemon/gvfsjobopenforread.c219
-rw-r--r--trunk/daemon/gvfsjobopenforread.h70
-rw-r--r--trunk/daemon/gvfsjobopenforwrite.c312
-rw-r--r--trunk/daemon/gvfsjobopenforwrite.h85
-rw-r--r--trunk/daemon/gvfsjobopeniconforread.c142
-rw-r--r--trunk/daemon/gvfsjobopeniconforread.h63
-rw-r--r--trunk/daemon/gvfsjobpull.c217
-rw-r--r--trunk/daemon/gvfsjobpull.h67
-rw-r--r--trunk/daemon/gvfsjobpush.c217
-rw-r--r--trunk/daemon/gvfsjobpush.h67
-rw-r--r--trunk/daemon/gvfsjobqueryattributes.c190
-rw-r--r--trunk/daemon/gvfsjobqueryattributes.h70
-rw-r--r--trunk/daemon/gvfsjobqueryfsinfo.c184
-rw-r--r--trunk/daemon/gvfsjobqueryfsinfo.h66
-rw-r--r--trunk/daemon/gvfsjobqueryinfo.c201
-rw-r--r--trunk/daemon/gvfsjobqueryinfo.h69
-rw-r--r--trunk/daemon/gvfsjobqueryinforead.c144
-rw-r--r--trunk/daemon/gvfsjobqueryinforead.h67
-rw-r--r--trunk/daemon/gvfsjobqueryinfowrite.c144
-rw-r--r--trunk/daemon/gvfsjobqueryinfowrite.h67
-rw-r--r--trunk/daemon/gvfsjobread.c154
-rw-r--r--trunk/daemon/gvfsjobread.h69
-rw-r--r--trunk/daemon/gvfsjobseekread.c151
-rw-r--r--trunk/daemon/gvfsjobseekread.h72
-rw-r--r--trunk/daemon/gvfsjobseekwrite.c151
-rw-r--r--trunk/daemon/gvfsjobseekwrite.h71
-rw-r--r--trunk/daemon/gvfsjobsetattribute.c192
-rw-r--r--trunk/daemon/gvfsjobsetattribute.h68
-rw-r--r--trunk/daemon/gvfsjobsetdisplayname.c178
-rw-r--r--trunk/daemon/gvfsjobsetdisplayname.h68
-rw-r--r--trunk/daemon/gvfsjobsource.c107
-rw-r--r--trunk/daemon/gvfsjobsource.h62
-rw-r--r--trunk/daemon/gvfsjobtrash.c156
-rw-r--r--trunk/daemon/gvfsjobtrash.h63
-rw-r--r--trunk/daemon/gvfsjobunmount.c169
-rw-r--r--trunk/daemon/gvfsjobunmount.h62
-rw-r--r--trunk/daemon/gvfsjobunmountmountable.c196
-rw-r--r--trunk/daemon/gvfsjobunmountmountable.h66
-rw-r--r--trunk/daemon/gvfsjobwrite.c153
-rw-r--r--trunk/daemon/gvfsjobwrite.h71
-rw-r--r--trunk/daemon/gvfskeyring.c133
-rw-r--r--trunk/daemon/gvfskeyring.h53
-rw-r--r--trunk/daemon/gvfsmonitor.c323
-rw-r--r--trunk/daemon/gvfsmonitor.h67
-rw-r--r--trunk/daemon/gvfsreadchannel.c290
-rw-r--r--trunk/daemon/gvfsreadchannel.h60
-rw-r--r--trunk/daemon/gvfswritechannel.c226
-rw-r--r--trunk/daemon/gvfswritechannel.h60
-rw-r--r--trunk/daemon/http.mount.in5
-rw-r--r--trunk/daemon/libsmb-compat.h200
-rw-r--r--trunk/daemon/localtest.mount.in4
-rw-r--r--trunk/daemon/main.c131
-rw-r--r--trunk/daemon/mount.c1280
-rw-r--r--trunk/daemon/mount.h37
-rw-r--r--trunk/daemon/network.mount.in4
-rw-r--r--trunk/daemon/obexftp-marshal.list5
-rw-r--r--trunk/daemon/obexftp.mount.in4
-rw-r--r--trunk/daemon/pty_open.c843
-rw-r--r--trunk/daemon/pty_open.h65
-rw-r--r--trunk/daemon/sftp.h87
-rw-r--r--trunk/daemon/sftp.mount.in8
-rw-r--r--trunk/daemon/smb-browse.mount.in6
-rw-r--r--trunk/daemon/smb.mount.in5
-rw-r--r--trunk/daemon/soup-input-stream.c921
-rw-r--r--trunk/daemon/soup-input-stream.h78
-rw-r--r--trunk/daemon/soup-output-stream.c417
-rw-r--r--trunk/daemon/soup-output-stream.h63
-rw-r--r--trunk/daemon/trash.mount.in5
-rw-r--r--trunk/daemon/trashlib/COPYING674
-rw-r--r--trunk/daemon/trashlib/Makefile.am15
-rw-r--r--trunk/daemon/trashlib/dirwatch.c313
-rw-r--r--trunk/daemon/trashlib/dirwatch.h28
-rw-r--r--trunk/daemon/trashlib/trashdir.c379
-rw-r--r--trunk/daemon/trashlib/trashdir.h36
-rw-r--r--trunk/daemon/trashlib/trashexpunge.c136
-rw-r--r--trunk/daemon/trashlib/trashexpunge.h17
-rw-r--r--trunk/daemon/trashlib/trashitem.c536
-rw-r--r--trunk/daemon/trashlib/trashitem.h59
-rw-r--r--trunk/daemon/trashlib/trashwatcher.c340
-rw-r--r--trunk/daemon/trashlib/trashwatcher.h23
-rw-r--r--trunk/dbus.txt83
-rw-r--r--trunk/gconf/Makefile.am32
-rw-r--r--trunk/gconf/gapplookupgconf.c185
-rw-r--r--trunk/gconf/gapplookupgconf.h51
-rw-r--r--trunk/gconf/gconf-module.c45
-rw-r--r--trunk/monitor/Makefile.am10
-rw-r--r--trunk/monitor/gphoto2/Makefile.am62
-rw-r--r--trunk/monitor/gphoto2/ggphoto2volume.c512
-rw-r--r--trunk/monitor/gphoto2/ggphoto2volume.h60
-rw-r--r--trunk/monitor/gphoto2/ggphoto2volumemonitor.c611
-rw-r--r--trunk/monitor/gphoto2/ggphoto2volumemonitor.h54
-rw-r--r--trunk/monitor/gphoto2/gphoto2-volume-monitor-daemon.c43
-rw-r--r--trunk/monitor/gphoto2/gphoto2.monitor4
-rw-r--r--trunk/monitor/gphoto2/hal-device.c297
-rw-r--r--trunk/monitor/gphoto2/hal-device.h93
-rw-r--r--trunk/monitor/gphoto2/hal-marshal.c163
-rw-r--r--trunk/monitor/gphoto2/hal-marshal.h36
-rw-r--r--trunk/monitor/gphoto2/hal-marshal.list3
-rw-r--r--trunk/monitor/gphoto2/hal-pool.c458
-rw-r--r--trunk/monitor/gphoto2/hal-pool.h74
-rw-r--r--trunk/monitor/gphoto2/hal-utils.c142
-rw-r--r--trunk/monitor/gphoto2/hal-utils.h40
-rw-r--r--trunk/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in3
-rw-r--r--trunk/monitor/hal/Makefile.am62
-rw-r--r--trunk/monitor/hal/ghaldrive.c936
-rw-r--r--trunk/monitor/hal/ghaldrive.h62
-rw-r--r--trunk/monitor/hal/ghalmount.c1132
-rw-r--r--trunk/monitor/hal/ghalmount.h76
-rw-r--r--trunk/monitor/hal/ghalvolume.c986
-rw-r--r--trunk/monitor/hal/ghalvolume.h84
-rw-r--r--trunk/monitor/hal/ghalvolumemonitor.c1360
-rw-r--r--trunk/monitor/hal/ghalvolumemonitor.h59
-rw-r--r--trunk/monitor/hal/hal-device.c297
-rw-r--r--trunk/monitor/hal/hal-device.h93
-rw-r--r--trunk/monitor/hal/hal-marshal.list3
-rw-r--r--trunk/monitor/hal/hal-pool.c458
-rw-r--r--trunk/monitor/hal/hal-pool.h74
-rw-r--r--trunk/monitor/hal/hal-utils.c171
-rw-r--r--trunk/monitor/hal/hal-utils.h42
-rw-r--r--trunk/monitor/hal/hal-volume-monitor-daemon.c43
-rw-r--r--trunk/monitor/hal/hal.monitor5
-rw-r--r--trunk/monitor/hal/org.gtk.Private.HalVolumeMonitor.service.in3
-rw-r--r--trunk/monitor/proxy/Makefile.am68
-rw-r--r--trunk/monitor/proxy/gproxydrive.c731
-rw-r--r--trunk/monitor/proxy/gproxydrive.h55
-rw-r--r--trunk/monitor/proxy/gproxymount.c665
-rw-r--r--trunk/monitor/proxy/gproxymount.h56
-rw-r--r--trunk/monitor/proxy/gproxyshadowmount.c465
-rw-r--r--trunk/monitor/proxy/gproxyshadowmount.h59
-rw-r--r--trunk/monitor/proxy/gproxyvolume.c1229
-rw-r--r--trunk/monitor/proxy/gproxyvolume.h67
-rw-r--r--trunk/monitor/proxy/gproxyvolumemonitor.c1354
-rw-r--r--trunk/monitor/proxy/gproxyvolumemonitor.h77
-rw-r--r--trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.c1755
-rw-r--r--trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.h35
-rw-r--r--trunk/monitor/proxy/remote-volume-monitor-module.c75
-rw-r--r--trunk/po/.gitignore14
-rw-r--r--trunk/po/ChangeLog1576
-rw-r--r--trunk/po/LINGUAS58
-rw-r--r--trunk/po/POTFILES.in91
-rw-r--r--trunk/po/ar.po1586
-rw-r--r--trunk/po/as.po1645
-rw-r--r--trunk/po/be@latin.po1681
-rw-r--r--trunk/po/bg.po1635
-rw-r--r--trunk/po/bn_IN.po1657
-rw-r--r--trunk/po/ca.po1752
-rw-r--r--trunk/po/cs.po1644
-rw-r--r--trunk/po/da.po1658
-rw-r--r--trunk/po/de.po1684
-rw-r--r--trunk/po/el.po1853
-rw-r--r--trunk/po/en_GB.po1652
-rw-r--r--trunk/po/es.po1670
-rw-r--r--trunk/po/et.po1556
-rw-r--r--trunk/po/eu.po1629
-rw-r--r--trunk/po/fi.po1624
-rw-r--r--trunk/po/fr.po1647
-rw-r--r--trunk/po/ga.po1524
-rw-r--r--trunk/po/gl.po1596
-rw-r--r--trunk/po/gu.po1612
-rw-r--r--trunk/po/he.po1674
-rw-r--r--trunk/po/hi.po1348
-rw-r--r--trunk/po/hu.po1632
-rw-r--r--trunk/po/it.po1714
-rw-r--r--trunk/po/ja.po1635
-rw-r--r--trunk/po/kn.po1529
-rw-r--r--trunk/po/ko.po1661
-rw-r--r--trunk/po/ku.po1362
-rw-r--r--trunk/po/lt.po1675
-rw-r--r--trunk/po/lv.po1603
-rw-r--r--trunk/po/mk.po1556
-rw-r--r--trunk/po/ml.po1564
-rw-r--r--trunk/po/mr.po1644
-rw-r--r--trunk/po/nb.po1627
-rw-r--r--trunk/po/nl.po1667
-rw-r--r--trunk/po/nn.po1350
-rw-r--r--trunk/po/or.po1631
-rw-r--r--trunk/po/pa.po1350
-rw-r--r--trunk/po/pl.po1884
-rw-r--r--trunk/po/pt.po1687
-rw-r--r--trunk/po/pt_BR.po1705
-rw-r--r--trunk/po/ro.po1806
-rw-r--r--trunk/po/ru.po1682
-rw-r--r--trunk/po/sk.po2418
-rw-r--r--trunk/po/sl.po1816
-rw-r--r--trunk/po/sq.po1615
-rw-r--r--trunk/po/sr.po2737
-rw-r--r--trunk/po/sr@latin.po2737
-rw-r--r--trunk/po/sv.po2116
-rw-r--r--trunk/po/ta.po1667
-rw-r--r--trunk/po/te.po1626
-rw-r--r--trunk/po/th.po1674
-rw-r--r--trunk/po/tr.po1650
-rw-r--r--trunk/po/uk.po1558
-rw-r--r--trunk/po/vi.po1805
-rw-r--r--trunk/po/zh_CN.po1799
-rw-r--r--trunk/po/zh_HK.po1652
-rw-r--r--trunk/po/zh_TW.po1657
-rw-r--r--trunk/programs/Makefile.am85
-rwxr-xr-xtrunk/programs/gvfs-bash-completion.sh64
-rw-r--r--trunk/programs/gvfs-cat.c193
-rw-r--r--trunk/programs/gvfs-copy.c193
-rw-r--r--trunk/programs/gvfs-info.c386
-rwxr-xr-xtrunk/programs/gvfs-less23
-rw-r--r--trunk/programs/gvfs-ls.c437
-rw-r--r--trunk/programs/gvfs-mkdir.c95
-rw-r--r--trunk/programs/gvfs-monitor-dir.c116
-rw-r--r--trunk/programs/gvfs-monitor-file.c105
-rw-r--r--trunk/programs/gvfs-mount.c951
-rw-r--r--trunk/programs/gvfs-move.c184
-rw-r--r--trunk/programs/gvfs-open.c170
-rw-r--r--trunk/programs/gvfs-rename.c80
-rw-r--r--trunk/programs/gvfs-rm.c69
-rw-r--r--trunk/programs/gvfs-save.c184
-rw-r--r--trunk/programs/gvfs-trash.c70
-rw-r--r--trunk/programs/gvfs-tree.c280
-rw-r--r--trunk/test/Makefile.am20
-rw-r--r--trunk/test/benchmark-common.c217
-rw-r--r--trunk/test/benchmark-gvfs-big-files.c191
-rw-r--r--trunk/test/benchmark-gvfs-small-files.c191
-rw-r--r--trunk/test/benchmark-posix-big-files.c192
-rw-r--r--trunk/test/benchmark-posix-small-files.c192
-rw-r--r--trunk/test/test-query-info-stream.c294
-rw-r--r--trunk/txt/gvfs_dbus.txt65
-rw-r--r--trunk/txt/ops.txt140
-rw-r--r--trunk/txt/rfc3986.txt3419
-rw-r--r--trunk/txt/rfc3987.txt2579
-rw-r--r--trunk/txt/vfs-ideas.txt425
-rw-r--r--trunk/txt/vfs-names.txt142
387 files changed, 210300 insertions, 0 deletions
diff --git a/trunk/.gitignore b/trunk/.gitignore
new file mode 100644
index 00000000..373ad3c9
--- /dev/null
+++ b/trunk/.gitignore
@@ -0,0 +1,33 @@
+Makefile
+Makefile.in
+*~
+*.o
+*.la
+*.lo
+*.exe
+.deps
+.libs
+test
+aclocal.m4
+autom4te.cache
+config.cache
+config.h
+config.h.in
+config.h.win32
+config.log
+config.status
+config.guess
+config.sub
+configure
+libtool
+depcomp
+ltmain.sh
+install-sh
+missing
+mkinstalldirs
+stamp-h1
+core.*
+core
+compile
+gtk-doc.make
+*.pc
diff --git a/trunk/AUTHORS b/trunk/AUTHORS
new file mode 100644
index 00000000..a6420004
--- /dev/null
+++ b/trunk/AUTHORS
@@ -0,0 +1,65 @@
+Overall Superhero (Desgin, Implementation, etc pp)
+==================================================
+Alexander Larsson <alexl@redhat.com>
+
+
+FUSE Integration
+===============
+Hans Petter Jansson <hpj@novell.com>
+
+HAL Integration
+===============
+David Zeuthen <davidz@redhat.com>
+
+Keyring Integration
+===================
+Carlos Garcia Campos <carlosgc@gnome.org>
+
+Backends
+=====================================
+
+CDDA backend
+============
+David Zeuthen <davidz@redhat.com>
+
+Gphoto2 backend
+===============
+David Zeuthen <davidz@redhat.com>
+
+Archive Backend
+===============
+Benjamin Otte <otte@gnome.org>
+
+FTP Backend
+===========
+Benjamin Otte <otte@gnome.org>
+Andreas Henriksson <andreas@fatal.se>
+
+Http/WebDAV Backend
+===================
+Christian Kellner <gicmo@gnome.org>
+Dan Winship <danw@gnome.org>
+
+Network Backend
+===============
+Andrew Walton <awalton@svn.gnome.org>
+
+ObexFTP Backend
+===============
+Bastien Nocera <hadess@hadess.net>
+
+SFTP Backend
+===========
+Alexander Larsson <alexl@redhat.com>
+
+Smb Backend
+===========
+Alexander Larsson <alexl@redhat.com>
+
+Test Backend
+============
+Tomas Bzatek <tbzatek@redhat.com>
+
+Trash Backend
+=============
+Ryan Lortie <desrt@desrt.ca>
diff --git a/trunk/COPYING b/trunk/COPYING
new file mode 100644
index 00000000..bf50f20d
--- /dev/null
+++ b/trunk/COPYING
@@ -0,0 +1,482 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/trunk/CVSVERSION b/trunk/CVSVERSION
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/trunk/CVSVERSION
diff --git a/trunk/ChangeLog b/trunk/ChangeLog
new file mode 100644
index 00000000..aa66a686
--- /dev/null
+++ b/trunk/ChangeLog
@@ -0,0 +1,6553 @@
+2009-03-16 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+ * configure.ac:
+ Bump version to 1.2.0
+
+2009-03-13 Alexander Larsson <alexl@redhat.com>
+
+ Bug 563418 – gvfs backend leaks monitors
+
+ * daemon/gvfsmonitor.c:
+ (unsubscribe):
+ (vfs_monitor_message_callback):
+ Fix crashes when unsubscribing monitors.
+
+2009-03-13 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/daemon-main.c (daemon_parse_args):
+ Enable debug output if GVFS_DEBUG is set in the environment.
+
+2009-03-12 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendgphoto2.c:
+ (ensure_ignore_prefix):
+ Make sure we ignore broken stores the same way we do in the
+ volume monitor.
+
+2009-03-11 Alexander Larsson <alexl@redhat.com>
+
+ Bug 572521 – gvfsd-cdda create two different Audio Disc Icons on Desktop
+
+ * daemon/gvfsbackendcomputer.c (recompute_files):
+ Don't show shadowed mounts.
+
+2009-03-10 Alexander Larsson <alexl@redhat.com>
+
+ Bug 563418 – gvfs backend leaks monitors
+
+ * client/gdaemonfilemonitor.c:
+ (g_daemon_file_monitor_cancel):
+ Actually pass in object_path in unsubscribe message
+
+2009-03-10 Alexander Larsson <alexl@redhat.com>
+
+ Bug 574754 – 100% cpu usage when connecting to a ssh key and denying key access
+
+ * daemon/gvfsbackendsftp.c (read_reply_sync):
+ Make sure we handle ssh exiting early.
+
+2009-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.8 ===
+
+2009-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ (handle_login):
+ Don't ask for username when getting ssh key passphrase
+
+2009-03-09 Alexander Larsson <alexl@redhat.com>
+
+ Bug 543064 – configure script does not pick up giomoduledir
+
+ * configure.ac:
+ Don't pass --define-variable libdir when getting giomoduledir.
+ This was added wrongly before.
+
+2009-03-09 Alexander Larsson <alexl@redhat.com>
+
+ Bug 523732 – gvfs-bash-completion.sh should not modify COMP_WORDBREAKS
+
+ * programs/gvfs-bash-completion.sh:
+ Don't override COMP_WORDBREAKS, instead workaround the colon problem
+
+2009-03-09 Alexander Larsson <alexl@redhat.com>
+
+ Bug 551683 – archive backend says file doesn't exist for directories
+
+ * daemon/gvfsbackendarchive.c:
+ (do_open_for_read):
+ Return G_IO_ERROR_IS_DIRECTORY if opening directory.
+
+2009-03-09 Alexander Larsson <alexl@redhat.com>
+
+ Bug 570888 – gvfs-gphoto2 mount 4 devices when pluging one camera
+
+ * monitor/gphoto2/ggphoto2volumemonitor.c:
+ (get_stores_for_camera):
+ Ignore stores that have 0 byte capability.
+
+2009-03-08 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ Bug 533219 - anonymous ftp login not working
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_login):
+ replace the empty string with the default password
+
+2009-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * ChangeLog:
+ * daemon/daemon-main.c:
+ Only spew g_debug if backend started with --debug
+
+2009-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/daemon-main.c:
+ * daemon/gvfsbackend.c:
+ * daemon/gvfsbackendburn.c:
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendobexftp.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsdaemon.c:
+ * daemon/gvfsjobcloseread.c:
+ * daemon/gvfsjobclosewrite.c:
+ * daemon/gvfsjobcopy.c:
+ * daemon/gvfsjobdbus.c:
+ * daemon/gvfsjobenumerate.c:
+ * daemon/gvfsjobmount.c:
+ * daemon/gvfsjobmove.c:
+ * daemon/gvfsjobpull.c:
+ * daemon/gvfsjobpush.c:
+ * daemon/gvfsjobread.c:
+ * daemon/gvfsjobseekread.c:
+ * daemon/gvfsjobseekwrite.c:
+ * daemon/gvfsjobunmount.c:
+ * daemon/gvfsjobwrite.c:
+ * daemon/mount.c:
+ Convert all spew to g_debug()
+
+2009-03-06 Alexander Larsson <alexl@redhat.com>
+
+ Bug 535814 – hangup on g_input_stream_close after cancelling from other thread
+ * daemon/gvfschannel.c:
+ Reverted patch from bug 522192 as it caused bug 535814.
+ Furthermore, its just wrong. We don't cancel streams as such, we
+ cancel individual operations on the stream.
+
+2009-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ (iterate_read_state_machine):
+ (iterate_close_state_machine):
+ (iterate_seek_state_machine):
+ (iterate_query_state_machine):
+ Don't send cancel when partial header read, as that
+ would throw away the part of the headers read so far.
+
+2009-03-05 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsmountinfo.c:
+ Updated .xdg-volume-info format as per bug 551403:
+ + Group name is "Volume Info"
+ + Icon is not translated
+ + support IconFile key
+
+2009-03-05 Alexander Larsson <alexl@redhat.com>
+
+ * monitor/hal/ghaldrive.c:
+ * monitor/hal/ghalmount.c:
+ * monitor/hal/ghalvolume.c:
+ * monitor/hal/ghalvolumemonitor.c:
+ Remove all locking (not needed since we're now
+ a single threaded process).
+ Don't emit signals in idle, thus risking callback
+ reordering. We don't need this anymore as it was
+ part of the locking structure.
+
+ This should fix the "No mount object for mounted
+ volume" error when mounting.
+
+2009-03-05 Alexander Larsson <alexl@redhat.com>
+
+ Bug 564003 – gvfs Cygwin patches
+
+ * common/Makefile.am:
+ Add -no-undefined required for cygwin build
+
+2009-03-05 Alexander Larsson <alexl@redhat.com>
+
+ Bug 569199 – incorrectly open smb workgroup using a space
+
+ * client/gvfsuriutils.c (g_vfs_encode_uri),
+ (g_vfs_decode_uri):
+ Escape and unescape host part too. This means we handle
+ e.g. smb workgroups with spaces in them. Allowing
+ escapes in hostnames complies with RFC 3986.
+
+ * client/gdaemonvfs.c (get_mountspec_from_uri):
+ Fix indentation
+
+2009-03-05 Alexander Larsson <alexl@redhat.com>
+
+ Bug 573381 – Memory leak in ftp_connection_parse_features()
+
+ * daemon/gvfsbackendftp.c (ftp_connection_parse_features):
+ Don't leak supported.
+
+2009-03-04 Alexander Larsson <alexl@redhat.com>
+
+ Bug 573837 – gvfs-fuse does not support ftruncate size != 0
+
+ * client/gvfsfusedaemon.c:
+ Support ftruncate to the current size as a NOP.
+ Fixes OOo saving
+
+2009-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * monitor/proxy/gproxyvolumemonitor.c:
+ Break circular dependencies on dispose.
+
+2009-03-03 Alexander Larsson <alexl@redhat.com>
+
+ Bug 561172 – gnome-open fails on local URIs with anchors
+
+ * programs/gvfs-open.c:
+ Don't pass file:// uris with anchor as filename
+
+2009-03-03 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ Make argument const char * as per the glib change.
+
+2009-03-02 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/trashitem.c (trash_item_restore): set 'error' on
+ failure. Fixes a crasher when attempting a restore to somewhere we
+ don't have write permissions for.
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.7 ===
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-03-02 David Zeuthen <davidz@redhat.com>
+
+ Bug 551403 – Support Reading Volume Icon/Name Information
+ from .xdg-volume-info
+
+ * common/Makefile.am:
+ * common/gvfsmountinfo.[ch]: Move autorun file detection to common
+ library. Also add routines for detecting .xdg-volume-info files.
+
+ * monitor/hal/ghalmount.c: Use g_mount_info*() functions for
+ detecting autorun and .xdg-volume-info files.
+
+2009-03-02 Paolo Borelli <pborelli@katamail.com>
+
+ * daemon/gvfsbackendarchive.c:
+ Chain up finalize
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 547161 – http string leak
+
+ * client/httpuri.c (http_get_mount_info_for_path):
+ Fix leak
+
+2009-03-02 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendsftp.c:
+ Implement query_info on sftp streams
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 550929 – nautilus sftp:// doesn't read User in ~/.ssh/config
+
+ * daemon/gvfsbackendsftp.c:
+ Don't specify user unless requested explicitly by the uri.
+ Patch from Christian Neumair
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 569712 – Write comments for translators!
+
+ * common/gvfsdnssdresolver.c (service_resolver_timed_out):
+ Fix position of translator comments.
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 545025 – gvfs doesnt use hal storage.icon.drive/volume properties
+
+ * monitor/hal/ghaldrive.c:
+ * monitor/hal/ghalmount.c:
+ Use storage.icon.drive and storage.icon.volume, not
+ info.desktop.icon as per the spec.
+
+ Patch from Karl Relton
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 565041 – burn: Doesn't support move
+
+ * daemon/gvfsbackendburn.c:
+ Implement try_move based on patch from Fabio Bonelli.
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 569066 – gvfs' configure.ac uses non posix 'test' constructions
+
+ * configure.ac:
+ Use '=', not '==' for comparison
+ Patch from Alexis Ballier
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 564003 – gvfs Cygwin patches
+
+ * daemon/gvfsbackendsftp.c:
+ Include <sys/time.h> for struct timeval on cygwin
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 569203 – gvfsd-sftp crashed with SIGSEGV in strlen()
+
+ * daemon/gvfsbackendsftp.c:
+ Workaround crash, spew a warning to try to get information about this crash.
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 569712 – Write comments for translators!
+
+ * common/gvfsdnssdresolver.c:
+ Add some translator comments.
+ Patch from David Planella
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ Implement query_info on smb streams
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ Bug 573371 – Unsafe g_htonl() macro expansion
+
+ * client/gdaemonfileoutputstream.c (append_request):
+ * client/gdaemonfileinputstream.c (append_request):
+ Don't use ++ inside macro that may evaluate twice.
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.[ch]:
+ Remove unused functions. Pointed out by Tommi Rantala.
+
+2009-02-27 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/dirwatch.c:
+ * daemon/trashlib/dirwatch.h:
+ * daemon/trashlib/trashdir.c:
+ * daemon/trashlib/trashitem.c:
+
+ Use DirWatch only when watching (move broken manual-scan code out).
+ Fix a bunch of leaks.
+
+2009-02-27 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileoutputstream.c:
+ Support query info on output streams
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsjobqueryinfowrite.[ch]:
+ * daemon/gvfswritechannel.c:
+ Add query info write support.
+
+ * daemon/gvfsbackendtest.c:
+ Implement writing to files in test backend.
+ Implement query info on write
+
+ * test/test-query-info-stream.c:
+ Test g_file_output_stream_query_info().
+
+2009-02-27 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileoutputstream.c:
+ Add and use g_string_remove_in_front helper function.
+
+2009-02-27 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ Support async query info
+
+ * test/test-query-info-stream.c:
+ Test async query info
+
+2009-02-27 Alexander Larsson <alexl@redhat.com>
+
+ * common/Makefile.am:
+ * common/gvfsfileinfo.[ch]:
+ Add (de)marshalling functions for GFileInfos.
+
+ * common/gvfsdaemonprotocol.h:
+ Add protocol extensions for query info over streams
+
+ * client/gdaemonfileinputstream.c:
+ Support sync query_info.
+
+ * daemon/Makefile.am:
+ * daemon/gvfsjobqueryinforead.[ch]:
+ * daemon/gvfsbackend.h:
+ Added query info job and backend call for input streams
+
+ * daemon/gvfsbackendtest.c:
+ Implement query_info_on_read
+
+ * daemon/gvfschannel.[ch]:
+ Add g_vfs_channel_send_info
+
+ * daemon/gvfsreadchannel.c:
+ (read_channel_handle_request):
+ Handle query info
+
+ * test/Makefile.am:
+ * test/test-query-info-stream.c:
+ Add test for stream query info.
+
+2009-02-26 Alexander Larsson <alexl@redhat.com>
+
+ Bug 570977 – sftp backend sends trailing zeros to communication data
+
+ * daemon/gvfsbackendsftp.c (get_data_from_command_stream):
+ Use g_memory_output_stream_get_data_size instead of old
+ workaround.
+ Patch from Pekka Vuorela
+
+2009-02-26 David Zeuthen <davidz@redhat.com>
+
+ Implement --device option for gvfs-mount.
+
+ This allows things like this
+
+ $ gvfs-mount -d /dev/sdb3
+ The device "Generic STORAGE DEVICE" contains encrypted data on partition 3.
+ Password:
+ Mounted /dev/dm-0 at /media/Encrypted Stuff
+
+ Reviewed by: Alexander Larsson <alexl@redhat.com>
+
+ * programs/gvfs-mount.c: See above.
+
+2009-02-26 David Zeuthen <davidz@redhat.com>
+
+ Lots of proxy monitor fixes.
+
+ Reviewed by: Alexander Larsson <alexl@redhat.com>
+
+ o add support for proxying GMountOperation to the remote volume
+ monitor process.
+
+ o add support for proxying GCancellable to the remote volume
+ monitor process.
+
+ o make each volume monitor process track callers and cancels
+ operations initiated by callers that disconnects from the bus
+
+ o makes the client side proxy monitor track the remote monitor. If
+ the monitor process disconnects, then all drives/volumes/mounts
+ are removed. If the monitor process reconnects, we reseed the
+ internal monitor and add drives/volumes/mounts.
+
+ o Each monitor process now uses ALLOW_REPLACEMENT when claiming a
+ name and also kills itself on NameLost (e.g. if it is
+ replaced). Coupled with the above disconnection/reconnection logic
+ it this makes it a lot more tolerable to hack on a remote volume
+ monitor. Simply just compile it, start it and the
+ existing (system-wide) copy will kill itself. And all the
+ clients (Nautilus, panel, drive applet, gvfsd-computer, etc.) will
+ reconnect and do the right thing.
+
+ o make the get_mount_for_mount_path() method on the class
+ GNativeVolumeMonitor actually work. It turns out that at least
+ gvfs-mount -u needs that.
+
+ o use /org/gtk/Private/RemoteVolumeMonitor instead of / as the
+ object name. Cf. the version D-Bus debacle on Lennart Poettering's
+ blog.
+
+ o make the proxy monitor client module resident
+
+ o For shadow mounts, redirect can_eject() and eject() to the
+ volume for the shadow mount. Without this patch eject on
+ e.g. cdda:// volumes won't work since cdda:// volumes are
+ GDaedmonMount and these don't implement eject.
+
+ * monitor/proxy/*.[ch]: See above.
+
+2009-02-26 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c (vfs_ftruncate): Immediately close the stream
+ we get from g_file_replace(), so truncation becomes visible. Fixes
+ BRC #479199.
+
+2009-02-26 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c (try_make_symlink):
+ Fix order of SSH_FXP_SYMLINK arguments. It seems
+ openssh is not following the docs here.
+
+2009-02-24 Paolo Borelli <pborelli@katamail.com>
+
+ * test/benchmark-posix-small-files.c:
+ * test/benchmark-posix-big-files.c:
+ * daemon/trashlib/dirwatch.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * client/gvfsfusedaemon.c:
+ Always use g_strerror
+
+2009-02-24 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ (ftp_connection_ensure_data_connection_pasv):
+ remove unused variable
+
+2009-02-24 Benjamin Otte <otte@gnome.org>
+
+ Bug 525283 - handle short reads in ftp
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_receive):
+ fix usage of n_bytes variable that changed meaning with the last ftp
+ fixes.
+ Spotted by Filippo Argiolas <filippo.argiolas@gmail.com>
+
+2009-02-22 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ fix typo in my name (thx Wouter)
+
+2009-02-20 David Zeuthen <davidz@redhat.com>
+
+ Make the gphoto2 backend work with buggy devices (such as the
+ iPhone) where the basedir of the store changes.
+
+ * daemon/gvfsbackendgphoto2.c: Revert the patch from #520123 that
+ removed the ignore_prefix handling. Change ensure_ignore_prefix()
+ to only use an ignore prefix if there is exactly one storage head.
+
+ * monitor/gphoto2/ggphoto2volumemonitor.c: Nuke orphan mount
+ handling since that is superseeded by shadow mounts. Also avoid
+ appending the store name if there is only one storage head.
+
+ * monitor/gphoto2/ggphoto2volume.[ch]: Rename foreign_mount_root
+ to activation_root since that is really what it is now. Also
+ fix a silly logical bug whereby music players (as reported by
+ HAL) weren't detected.
+
+2009-02-19 Benjamin Otte <otte@gnome.org>
+
+ * AUTHORS:
+ * daemon/gvfsbackendftp.c:
+ add Andreas as author of the ftp backend
+
+2009-02-19 Benjamin Otte <otte@gnome.org>
+
+ reviewed by: Andreas Henriksson <andreas@fatal.se>
+
+ Bug 525283 - handle short reads in ftp
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_receive):
+ account for cases where soup_socket_read_until() would not read up to
+ the boundary on the first read.
+
+2009-02-18 Alexander Larsson <alexl@redhat.com>
+
+ Bug 563623 – build dies on platforms lacking poll() implimentation
+
+ * client/gvfsdaemondbus.c:
+ (setup_async_fd_receive):
+ (_g_vfs_daemon_call_sync):
+ Use g_poll instead of poll.
+ Patch from ephraim_owns@hotmail.com
+
+2009-02-17 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/trashwatcher.c: rescan NFS mounts when enumerating
+ trash (since not all change events are reported).
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.6 ===
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c (replace_create_temp_reply):
+ Return G_IO_ERROR_CANT_CREATE_BACKUP in the below case instead
+ of not copying the ownership.
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ Bug 546482 – Keep ownership when replacing files on sftp
+
+ * daemon/gvfsbackendsftp.c:
+ Try to copy ownership. If this fails revert to truncate
+ and overwrite, unless make_backup is set.
+ Ideally we should handle the backup case too, but that
+ requires more code.
+
+ Patch from Jesse van den Kieboom.
+
+2009-02-16 Christian Kellner <gicmo@gnome.org>
+
+ Bug 546256 – Crash in g_vfs_get_file_for_uri()
+
+ * client/httpuri.c: Make sure we never return a non-NULL
+ GVfsUriMountInfo with the path component set to NULL, since
+ this leads to dead kittens.
+ NB: This only fixes the symptom. The real problem is deep in
+ the uri parsing logic.
+
+2009-02-16 Christian Kellner <gicmo@gnome.org>
+
+ 536305 – incorrect GError propagation in the htt
+
+ * daemon/gvfsbackenddav.c: Convert soup errors to
+ gio errors. Patch from Jesse van den Kieboom
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ Bug 529349 – Redirects with username doesn't work
+
+ * daemon/gvfsbackenddav.c: (redirect_handler):
+ Copy username and password when redirecting.
+ Patch from Mads Chr. Olesen
+
+2009-02-16 Alexander Larsson <alexl@redhat.com>
+
+ Bug 566452 – Error when creating folder on webdav share
+
+ * daemon/gvfsbackenddav.c:
+ (redirect_handler):
+ Don't intercept "201 Created" return as a redirection
+ Patch from Mads Chr. Olesen
+
+2009-02-13 Cosimo Cecchi <cosimoc@gnome.org>
+
+ Bug 570533 – use g_set_error_literal
+
+ * daemon/gvfsbackendobexftp.c: (_push_single_file_helper):
+ * daemon/gvfsbackendtrash.c: (trash_backend_get_file),
+ (trash_backend_open_for_read), (trash_backend_delete),
+ (trash_backend_pull):
+ * daemon/trashlib/trashitem.c: (trash_item_delete):
+ use g_set_error_literal() when appropriate.
+ Patch by Christian Persch.
+
+2009-02-13 Cosimo Cecchi <cosimoc@gnome.org>
+
+ Bug 531705 – Won't build with libarchive 1.3.1
+
+ * configure.ac: check for archive_entry_filetype() instead of
+ archive_read_open(). Patch from Tom Parker.
+
+2009-02-05 Bastien Nocera <hadess@hadess.net>
+
+ Bug 563788 – GNOME Goal: Clean up GLib and GTK+ includes
+
+ * client/gvfsuriutils.h:
+ * daemon/gvfsbackendburn.c:
+ * daemon/gvfsbackendcomputer.c:
+ * daemon/gvfsbackenddnssd.c:
+ * daemon/gvfsbackendnetwork.c:
+ * daemon/gvfsdaemonutils.c:
+ * daemon/mount.c: Fix build for single GTK+ include, patch
+ from Luis Menina <liberforce@freeside.fr> (Closes: #563788)
+
+2009-02-04 Ryan Lortie <desrt@desrt.ca>
+
+ Bug 570481 – Please add translator comments
+
+ * daemon/gvfsbackendtrash.c: use clearer language to make it easier to
+ translate (not to mention, easier to understand in English).
+
+2009-02-03 Bastien Nocera <hadess@hadess.net>
+
+ Bug 570193 – Mounting phone connected via Bluetooth fails
+
+ * daemon/gvfsbackendobexftp.c (_get_bluetooth_device_properties):
+ Use a private connection to connect to the system D-Bus, thanks
+ to Alexander Larsson
+
+2009-02-03 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (do_mount): Fix
+ possible double-free when the display name is freed
+ Avoid errors when the icon name couldn't be gathered
+
+2009-02-02 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.5 ===
+
+2009-02-02 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-02-02 Bastien Nocera <hadess@hadess.net>
+
+ Bug 511671 - Make obex-ftp work over usb connections
+
+ * configure.ac: Require HAL for the ObexFTP backend
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendobexftp.c (_get_numbers_from_usb_path),
+ (_is_nokia_3650), (_get_bluetooth_name_and_icon),
+ (_get_bluetooth_device_properties), (_is_same_path),
+ (_find_ods_usb_intfnum), (_get_usb_intfnum_and_properties),
+ (do_mount): Add support for USB ObexFTP devices, original
+ patch from Alexander Kanavin <ak@sensi.org>, requires
+ current obex-data-server trunk
+
+2009-01-28 Ryan Lortie <desrt@desrt.ca>
+
+ Bug 512144 – symlinks to folders are deleted recursively
+
+ * desrt: place a paper bag over my face
+ * daemon/trashlib/trashexpunge.c: try a lot harder to not follow
+ symlinks.
+
+2009-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsicon.c:
+ (g_vfs_icon_to_tokens):
+ Dup string to avoid double free later.
+
+2009-01-28 Ryan Lortie <desrt@desrt.ca>
+
+ Bug 569480 – trash backend crashes due to invalid write
+
+ * daemon/trashlib/trashitem.c (trash_item_escape_name): correct
+ extremely silly mistake.
+
+ Problem caught by Seb's heroic valgrinding :)
+
+2009-01-28 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendobexftp.c: (_invalidate_cache_helper),
+ (do_mount), (push_transfer_started_cb),
+ (push_transfer_completed_cb), (push_transfer_progress_cb),
+ (push_data_free), (_push_single_file_helper), (do_push),
+ (do_make_directory), (g_vfs_backend_obexftp_class_init):
+ * daemon/obexftp-marshal.list:
+ Implement write support for the ObexFTP backend (#519071).
+
+2009-01-21 A. Walton <awalton@gnome.org>
+
+ * daemon/gvfsdaemon.c (daemon_schedule_exit):
+ * daemon/gvfsjobcreatemonitor.c (create_reply):
+ Use g_timeout_add_seconds() instead of g_timeout_add() to save
+ some power.
+
+2009-01-20 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackenddnssd.c: Some devices/systems
+ advertise SMB through zeroconf instead of NetBios,
+ displays Apple Time Capsules in nautilus (Closes: #568147)
+
+2009-01-20 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/gvfsbackendtrash.c: nail a couple of leaks
+
+2009-01-20 Sebastien Bacher <seb128@ubuntu.com>
+
+ * common/Makefile.am: use glib where it is required
+
+2009-01-19 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.4 ===
+
+2009-01-19 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-01-13 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c (getattr_for_file)
+ (vfs_open)
+ (vfs_create)
+ (vfs_rmdir)
+ (vfs_access): Get only the attributes we require. This speeds up
+ directory listings in particular, since we don't need to probe
+ individual files to determine their MIME types.
+
+2009-01-12 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/trashitem.c: don't insta-thaw deletes
+ * daemon/gvfsbackendtrash.c: use a timeout to only call thaw() once
+ per batch of delete method calls.
+
+2009-01-12 Matthias Clasen <mclasen@redhat.com>
+
+ * daemon/Makefile.am: Dist the dav+sd.mount.in file
+
+2009-01-07 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c: (recompute_files):
+ Remove unnecessary GError
+
+2009-01-06 Tomas Bzatek <tbzatek@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.3 ===
+
+2009-01-06 Tomas Bzatek <tbzatek@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2009-01-06 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/smb-browse.mount.in:
+ SMB browsing authentication support (#524485)
+ Make smb-browse backend not automounted
+ Mount smb root on network backend automount
+
+2009-01-05 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/COPYING: include text of GPL3 by request of Vincent.
+
+2008-12-30 Benjamin Otte <otte@gnome.org>
+
+ Bug 565504 - limited number of connections causes commands to fail
+
+ * daemon/gvfsbackendftp.c: (g_vfs_backend_ftp_pop_connection):
+ really fix this bug by not calling g_vfs_job_succeeded() on the error
+ path.
+
+2008-12-30 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (g_vfs_backend_ftp_pop_connection):
+ remove fixme for max connection tracking, by remembering the max
+ connections on the stack.
+
+2008-12-30 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_prepare),
+ (ftp_connection_use), (ftp_connection_ensure_data_connection_epsv),
+ (ftp_connection_ensure_data_connection_pasv),
+ (ftp_connection_try_cd), (g_vfs_backend_ftp_pop_connection),
+ (do_mount), (resolve_symlink), (do_enumerate):
+ introduce ftp_connection_clear_error() for clarity
+
+2008-12-30 Benjamin Otte <otte@gnome.org>
+
+ Bug 565504 - limited number of connections causes commands to fail
+
+ * daemon/gvfsbackendftp.c: (g_vfs_backend_ftp_pop_connection):
+ clear connection error before popping job, so that the error isn't
+ propagated to the job
+
+2008-12-16 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/trashlib/trashexpunge.c: set files to mode 700 before
+ deleting to deal with users trashing read-only directories
+
+2008-12-16 Ryan Lortie <desrt@desrt.ca>
+
+ Bug 562955 – parallel build doesn't work
+
+ * common/Makefile.am: use non-absolute path for libgvfscommon.la so
+ that automake can see the dependency
+
+2008-12-16 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/gvfsbackendtrash.c (trash_backend_add_info): add
+ trash::orig-path and trash::deletion-date info
+
+2008-12-15 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.2 ===
+
+2008-12-15 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsbackendtrash.h: relicense to LGPLv2+
+
+2008-12-15 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ * daemon/trashlib/Makefile.am:
+ Fix dist issues
+
+2008-12-15 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-12-12 Ryan Lortie <desrt@desrt.ca>
+
+ Fix memory leaks on trash backend
+
+ * daemon/trashlib/trashdir.c:
+ * daemon/trashlib/trashexpunge.c:
+ * daemon/trashlib/trashitem.c:
+ * daemon/trashlib/trashwatcher.c: fix memory leaks
+ * daemon/gvfsbackendtrash.c: fix leaks; split enumerate into two
+ functions (one for the root, one for the non-root case)
+
+2008-12-12 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ (ftp_connection_ensure_data_connection_pasv):
+ Fix successful PASV connections (don't try to apply workaround).
+ (fixes #564027)
+
+2008-12-11 Ryan Lortie <desrt@desrt.ca>
+
+ Implement pull support on trash backend.
+
+ * daemon/trashlib/trashitem.[ch]: add support for restoring items
+ * daemon/gvfsbackendtrash.c: implement pull
+
+2008-12-11 Ryan Lortie <desrt@desrt.ca>
+
+ New trash:/ backend.
+
+ * daemon/trashlib: implementation of the reader side of the fd.o
+ trash specification
+ * daemon/gvfsbackendtrash.[ch]: rewrite based on trashlib
+ * configure.ac: add daemon/trashlib/Makefile to output
+ * daemon/Makefile.am: add trashlib/ subdir and include in trash
+ backend libraries
+
+2008-12-11 Dan Winship <danw@gnome.org>
+
+ * configure.ac: require libsoup-gnome, for SoupProxyResolverGNOME
+
+ * daemon/gvfsbackendhttp.c (g_vfs_backend_http_init): add a
+ SoupProxyResolverGNOME to the sessions, to automatically handle
+ proxies. #522985
+
+2008-12-11 Dan Winship <danw@gnome.org>
+
+ * daemon/soup-input-stream.c (read_async_done)
+ (soup_input_stream_read_async, soup_input_stream_close_async):
+ don't leak GSimpleAsyncResults. #551075.
+
+ * daemon/gvfsbackendhttp.c (try_open_for_read): set_accumulate to
+ FALSE on the response body to avoid extra allocating+freeing.
+ Patch from Peter Christoffersen, part of #551075.
+ (open_for_read_ready): unref the stream on error.
+
+2008-12-09 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_query_file_info_helper): Fix icon
+ for the root directory of an obexftp server (Closes: #542687)
+
+2008-12-09 Bastien Nocera <hadess@hadess.net>
+
+ * monitor/gphoto2/Makefile.am:
+ * monitor/gphoto2/ggphoto2volumemonitor.c (get_stores_for_camera),
+ (update_cameras): For each camera discovered, create shadow mounts
+ for each one of the top-level storage heads, makes each of the
+ device's stores appear separately
+
+ * daemon/gvfsbackendgphoto2.c (monitors_emit_internal),
+ (release_device), (split_filename), (file_get_info), (do_mount),
+ (do_open_for_read_real), (do_query_info), (try_query_info),
+ (do_enumerate), (try_enumerate), (do_make_directory),
+ (do_set_display_name), (do_delete), (do_create_internal),
+ (do_replace), (do_append_to), (do_move), (do_create_dir_monitor),
+ (do_create_file_monitor): Remove all the hacks to handle
+ a single storage head differently from multiple storage heads,
+ this makes photo directories detection and the likes work
+ for multiple storage-heads
+
+ (Closes: #520123)
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ * client/gdaemonvolumemonitor.c:
+ * monitor/proxy/Makefile.am:
+ * monitor/proxy/gproxydrive.c:
+ * monitor/proxy/gproxymount.c:
+ * monitor/proxy/gproxyvolume.c:
+ * monitor/proxy/gproxyvolume.h:
+ * monitor/proxy/gproxyvolumemonitor.c:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/remote-volume-monitor-module.c:
+ * monitor/proxy/gproxyshadowmount.[ch]:
+ Use the new support for shadow mounts instead
+ of g_volume_monitor_adopt_orphan_mount
+
+ Patch from David Zeuthen (#555332)
+
+ * programs/gvfs-mount.c:
+ Add support to monitor volume monitor events
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 1.1.1 ===
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am (mount_in_files):
+ Dist dav+sd.mount
+
+ * NEWS:
+ Update for release
+
+2008-12-01 Bastien Nocera <hadess@hadess.net>
+
+ * configure.ac: Update bluez requirements, we
+ can't really require the 4.x API without the 4.x
+ libraries...
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ * common/gmounttracker.[ch]:
+ * daemon/gvfsbackend.[ch]:
+ Make mounts/backends have a GIcon not a icon name
+
+ * daemon/gvfsbackendsftp.c:
+ Support /etc/favicon.png
+
+ * daemon/gvfsbackendsmbbrowse.c:
+ Simplify some code with the new GIcon support
+
+ Patch from David Zeuthen (#557540)
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * common/Makefile.am:
+ * common/gvfsdnssdresolver.c: Added.
+ * common/gvfsdnssdresolver.h: Added.
+ * common/gvfsdnssdutils.c: Added.
+ * common/gvfsdnssdutils.h: Added.
+ * daemon/Makefile.am:
+ * daemon/dav+sd.mount.in: Added.
+ * daemon/dav.mount.in:
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackenddnssd.c:
+ * daemon/gvfsbackendnetwork.c:
+ For references to dns-sd dav services, use a
+ dav+sd: uri, since this is stable over e.g.
+ port changes and as such work better in e.g.
+ bookmarks.
+
+ Patch from David Zeuthen (#555436)
+
+2008-11-18 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Better name for the has-username case.
+
+2008-11-18 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ If user is specified, add to name too, so we get a unique fuse path
+
+2008-11-17 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_features):
+ use g_ascii_is_space() (thanks Wouter)
+
+2008-11-17 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ document what the workarounds do
+
+2008-11-17 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_prepare),
+ (ftp_connection_use):
+ If feat before login fails, try it again after login. (fixes bug
+ #556786, researched by Oliver Joos) So we're now "better than gftp and
+ filezilla together". Take that gnome-vfs!
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_features):
+ Deal with "\n" vs "\r\n" in FEAT responses. Researched by Oliver Joos.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_features):
+ Be less strict in leading spaces of FEAT reply.
+ Researched by Oliver Joos. Apparently common, one affected ftp server
+ visible in bug #556809.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_prepare),
+ (ftp_connection_use), (g_vfs_backend_ftp_pop_connection),
+ (do_mount):
+ Do FEAT and OPTS UTF8 ON before login. This mirros behavior of lftp.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ (ftp_connection_ensure_data_connection_epsv),
+ (ftp_connection_ensure_data_connection_pasv):
+ Add workarounds for EPSV/PASV data connection failures.
+ - don't use EPSV if we get successful return codes but fails to
+ connect.
+ - don't use address in PASV response if we fail to connect to it
+ (use the same address as the command connection is established to).
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ (_ftp_connection_ensure_data_connection),
+ (ftp_connection_ensure_data_connection_epsv),
+ (ftp_connection_ensure_data_connection_pasv),
+ (ftp_connection_ensure_data_connection):
+ Restructure ..._ensure_data_connection and fall back on PASV when EPSV
+ fails.
+ - split up ..._ensure_data_connection in subroutines
+ - make a full attempt to connect instead of relying on response
+ code from EPSV command.
+ - when EPSV data connection fails, try PASV.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_use):
+ Disable usage of "EPSV ALL". (fixes #547855). See in-source comment
+ for the reasons.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_use):
+ Use UTF8 when available.
+
+2008-11-17 Andreas Henriksson <andreas@fatal.se>
+
+ reviewed by: Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_features):
+ Add UTF8 to feature parsing.
+
+2008-11-10 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ * daemon/libsmb-compat.h:
+ Timestamp (mtime) setting support
+
+2008-11-06 Hans Petter Jansson <hpj@novell.com>
+
+ * gconf/gapplookupgconf.c (get_default_for_uri_scheme): Free command
+ string after use. Fixes a leak.
+
+2008-11-04 Tomas Bzatek <tbzatek@redhat.com>
+
+ * client/gdaemonmount.c: (g_daemon_mount_guess_content_type_sync):
+ Return an empty array on success when no content type matches
+
+2008-10-28 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (dir_default_iter_process):
+ Convert stuct tm from what ParseFTPList gives to what mktime expects.
+ Fixes wrong date/time parsing for FTP files.
+ Patch by Andreas Henriksson (#550837).
+
+2008-10-28 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (dir_default_init_data):
+ Use LIST -a instead of LIST on UNIX ftp sites.
+ Patch by Andreas Henriksson (#551822).
+
+2008-10-24 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ Don't ask for credentials twice when the password dialog was cancelled
+
+2008-10-24 Alexander Larsson <alexl@redhat.com>
+
+ * programs/gvfs-info.c (show_attributes):
+ Don't show fallback setting for GThemedIcon (this is a construct only property).
+ List icons on same line.
+
+2008-10-23 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsdaemonutils.c:
+ Don't return fallback icons, since that gives problems
+ with custom mime icons (#528320)
+
+2008-10-21 Alexander Larsson <alexl@redhat.com>
+
+ Patch from David Zeuthen (#557182)
+
+ * common/Makefile.am:
+ * common/gvfsicon.[ch]:
+ Added GVfsIcon object for GVfs backend specific icons.
+
+ * common/gmountspec.[ch]:
+ Make sure to/from string works correctly to roundtrip GMountSpec:s
+ Make GMountSpec a boxed type
+
+ * common/gvfsdaemonprotocol.h:
+ Add OpenIconForRead operation
+
+ * client/Makefile.am:
+ * client/gvfsiconloadable.[ch]:
+ In gvfs client side, implement GLoadableIcon for GVfsIcon type.
+
+ * client/gdaemonvfs.c:
+ Make sure that we add the GLoadableIcon interface for GVfsIcon on load
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.[ch]:
+ * daemon/gvfsjobopeniconforread.[ch]:
+ Add new job type for OpenIconForRead op
+
+ * daemon/gvfsbackendgphoto2.c:
+ Implement OpenIconForRead for icon previews.
+
+2008-10-21 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Require glib 2.19.1 for GIcon serialization support
+
+ * common/gvfsdaemonprotocol.c:
+ Use g_icon_to_string & co instead of home-brewed serialization
+
+ * monitor/proxy/gproxydrive.c:
+ * monitor/proxy/gproxymount.c:
+ * monitor/proxy/gproxyvolume.c:
+ * monitor/proxy/gproxyvolumemonitor.c:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c:
+ Use g_icon_to_string & co instead of home-brewed serialization
+
+2008-10-20 Richard Hughes <richard@hughsie.com>
+
+ reviewed by: Christian Kellner <ck@xatom.net>
+
+ * programs/gvfs-info.c: (show_attributes):
+ Whilst debugging an icon theme bug, I wanted to know what icon
+ would be chosen for a file. It turns out gvfs-info gets all the
+ properties and prints them, but for an icon prints:
+ standard::icon: GThemedIcon:0x8df7200
+ This isn't very helpful. I've fixed this to print out the icons and
+ the order they should be chosen like:
+ standard::icon: (fallbacks: FALSE)
+ 1. name:application-x-cd-image
+ 2. name:gnome-mime-application-x-cd-image
+ 3. name:application-x-generic
+ 4. name:text-x-generic
+
+2008-10-20 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ (run_sync_state_machine):
+ Revert debug spew from recent commit now that the core
+ issue is fixed (by the fuse race condition fix).
+
+2008-10-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c (try_create_dir_monitor):
+ Always fail the job when we don't support monitoring.
+
+ * client/gvfsfusedaemon.c (getattr_for_file):
+ Correct st_blocks rounding in previous commit
+
+2008-10-17 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.c (append_escaped_name):
+ Fix uninitialized memory read.
+
+2008-10-17 Hans Petter Jansson <hpj@novell.com>
+
+ Attempt to prevent potential race conditions in the FUSE backend
+ when file handles get closed while still in use in another thread,
+ if that ever happens.
+
+ * client/gvfsfusedaemon.c (file_handle_new): Insert new file
+ handles in global hash table of active file handles.
+ (file_handle_unref): Clarify the code and comments a little.
+ (file_handle_free): Remove file handle from global table of
+ active handles.
+ (reindex_file_handle_for_path)
+ (get_file_handle_for_path)
+ (get_or_create_file_handle_for_path): global_fh_table ->
+ global_path_to_fh_map.
+ (get_file_handle_from_info): New function that recovers our file
+ handle from a fuse_file_info struct, but only if it exists in
+ the global table of valid handles.
+ (vfs_getattr): Remove code that acquired and locked the file handle
+ for the path we operate on. No locking is required here.
+ (vfs_open): Assign file handle to fuse_file_info while holding lock.
+ Purely a formality that makes code easier to read.
+ (vfs_create): Ditto.
+ (vfs_release): Use get_file_handle_from_info () so the file handle
+ is validated.
+ (vfs_read): Hold a ref to the file handle while it's in use. If
+ handle is invalid, raise EINVAL.
+ (vfs_ftruncate): Ditto.
+ (vfs_write): Ditto.
+ (vfs_rename): Cosmetic change.
+ (vfs_unlink): Ditto.
+ (vfs_truncate): Add helpful comment.
+ (vfs_init): Create global table of active file handles.
+
+2008-10-16 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendftp.c:
+ (do_mount):
+ Show username in auth dialog if specified in uri (#554156)
+
+2008-10-16 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c (getattr_for_file):
+ Set st_blocks & co so that du works (#554682)
+ Patch from Andreas Henriksson
+
+2008-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ (run_sync_state_machine):
+ Add some debug spew and avoid crashing in case of code not properly
+ setting the GError, as reported on the list.
+
+2008-10-06 Alexander Larsson <alexl@redhat.com>
+
+ Patch from Andreas Henriksson
+
+ * daemon/gvfsbackendftp.c:
+ (dir_default_iter_new):
+ (dir_default_iter_process):
+ Don't read past start of filename. (#545971)
+
+2008-10-03 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (get_name_and_icon): Use
+ the Alias instead of the Name, so we automatically fallback
+ if the name isn't available
+
+2008-10-03 David Zeuthen <davidz@redhat.com>
+
+ * daemon/gvfsbackendgphoto2.c: Remove misleading comment about the
+ license (#554811)
+
+2008-10-02 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c: Re-add bluetooth.h include,
+ we still use bachk right now
+
+2008-10-02 Bastien Nocera <hadess@hadess.net>
+
+ * client/test-uri-utils.c: Add a few more test URIs
+
+2008-09-29 David Zeuthen <davidz@redhat.com>
+
+ * monitor/proxy/gproxyvolume.c (mount_cb): Complete the mounting
+ operation in idle to ensure we've processed pending dbus messages
+ for creating the new mount object
+
+2008-09-29 David Zeuthen <davidz@redhat.com>
+
+ * monitor/hal/ghalvolume.c:
+ * monitor/hal/ghalvolumemonitor.[ch]:
+ Make sure we emit 'mount-added' when forcing an update for
+ completing a mount operation (#552168)
+
+2008-09-29 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_is_nokia_3650),
+ (get_name_and_icon), (_get_device_properties),
+ (g_vfs_backend_obexftp_finalize), (g_vfs_backend_obexftp_init),
+ (_query_file_info_helper), (session_connect_error_cb),
+ (session_connected_cb), (do_mount),
+ (g_vfs_backend_obexftp_class_init):
+ * daemon/obexftp-marshal.list:
+ Port to BlueZ 4.x API and obex-data-server SVN API,
+ use the "Icon" property to get the icon, instead of parsing the
+ device class ourselves (#552356)
+
+2008-09-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.[ch]:
+ * common/gvfsdaemonprotocol.h:
+ * daemon/mount.c:
+ Reverse map fuse paths to gvfs uris in
+ g_file_new_for_path().
+
+2008-09-25 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.c:
+ (_g_dbus_get_file_attribute):
+ Free returned strv with g_strfreev, not dbus_free_string_array. (#529596)
+
+2008-09-23 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Bump version of unstable branch to 1.1.1
+
+2008-09-23 Alexander Larsson <alexl@redhat.com>
+
+ * monitor/proxy/gproxyvolumemonitor.[ch]:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/remote-volume-monitor-module.c:
+ Only call the IsSupported dbus call when the class
+ is actually needed instead of on gio init.
+ Don't integrate internal session bus with mainloop
+ during is_support code, as that is not necessary yet, and
+ it caused problem if done in a thread.
+
+ This fixes the trash crash issue in bug #547568.
+
+2008-09-23 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * common/Makefile.am:
+ * common/gmountsource.c:
+ * common/gmounttracker.c:
+ * monitor/gphoto2/Makefile.am:
+ * monitor/hal/Makefile.am:
+ * monitor/proxy/Makefile.am:
+ Link all modules against the installed libgvfscommon instead
+ of duplicating the statically linked one. This is safe wrt
+ namespace conflicts, because the modules are opened RTLD_LOCAL
+ so the dependencies will not pollute the global namespace.
+
+ * client/gdaemonvfs.c:
+ Make the gvfsdbus module persistant. This means we will never
+ unload it, and thus not unload libgvfscommon which could
+ be problematic. This is not a huge problem, as:
+ + The gio modules will not be loaded anyway unless you use gio
+ + The gvfsdbus module will be persistent anyway as soon as
+ the app references the GVfs object, which likely all gio apps do
+ + The module load order doesn't matter wrt unload order, because
+ all gio modules are loaded before any one is unloaded.
+
+2008-09-16 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ Kerberos authentication fixes. Fixes #524498
+ Inspired by the smb-browse patch from Steve Langasek
+
+2008-09-15 Tomas Bzatek <tbzatek@redhat.com>
+
+ * client/smburi.c:
+ Encode username and domain into the URI
+
+2008-09-15 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ Revert commit #1772.
+ Set the information on the mount spec from the original URI
+
+2008-09-15 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonfile.c:
+ Don't leak the GSimpleAsyncResult in find_enclosing_mount_async.
+ Patch by Matthias Clasen <mclasen@redhat.com) (#552295)
+
+2008-09-15 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileenumerator.c:
+ Add proper implementation of async file enumeration.
+ This avoids the problem with the default thread based ones
+ that could cause callbacks in the non-mainloop thread. (#551337)
+
+2008-09-15 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac: Fix gnome-keyring configure switch
+ Patch by Rémi Cardona <remi@gentoo.org> (#552126)
+
+2008-09-09 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Post-release version bump to 0.99.8.
+
+=== gvfs 0.99.7 ===
+
+2008-09-09 Hans Petter Jansson <hpj@novell.com>
+
+ * NEWS: Update for 0.99.7.
+
+2008-09-05 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendcdda.c (track_free), (release_metadata),
+ (fetch_metadata), (g_vfs_backend_cdda_finalize), (do_mount),
+ (do_unmount), (set_info_for_track), (do_query_info):
+ Export CD-Text metadata via xattrs (Closes: #550858)
+
+2008-09-02 David Zeuthen <davidz@redhat.com>
+
+ * monitor/hal/ghaldrive.c: (g_hal_drive_eject_do):
+ * monitor/hal/ghalmount.c: (unmount_cb), (unmount_do),
+ (eject_wrapper_callback), (g_hal_mount_eject):
+ * monitor/proxy/gproxymount.c: (eject_wrapper_callback),
+ (g_proxy_mount_eject):
+ * monitor/proxy/gproxyvolume.c: (eject_wrapper_callback):
+ Remember to refcount objects (#546971).
+
+2008-09-02 David Zeuthen <davidz@redhat.com>
+
+ * monitor/hal/ghalvolume.c (format_size_for_display): Add docs
+ explaining why powers of 10 are used.
+
+2008-09-02 David Zeuthen <davidz@redhat.com>
+
+ * monitor/hal/ghalvolume.c (do_update_from_hal): Revert patch from
+ bug 550100 - we really don't want to show "61.7MB Volume" instead
+ of "64M Volume".
+
+2008-09-01 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Post-release version bump to 0.99.7.
+
+=== gvfs 0.99.6 ===
+
+2008-09-01 Hans Petter Jansson <hpj@novell.com>
+
+ * NEWS: Update for 0.99.6.
+
+2008-09-01 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac:
+ Require libsoup >= 2.23.91
+
+2008-09-01 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsjobpull.c:
+ * daemon/gvfsjobpull.h:
+ New daemon method to pull files from daemons to the local
+ file system.
+
+ * daemon/gvfsjobpush.c:
+ * daemon/gvfsjobpush.h:
+ New daemon method to push local files to daemons. (Replaces
+ Upload)
+
+ * daemon/gvfsjobupload.c:
+ * daemon/gvfsjobupload.h:
+ Replaced by Push.
+
+ * common/gvfsdaemonprotocol.h:
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.c:
+ * daemon/gvfsbackend.h:
+ Add Push and Pull. Remove Upload.
+
+ * client/gdaemonfile.c:
+ New transfer logic. In case of move try push/pull (with
+ remove_source set to TRUE) first then fallback. In case of copy
+ try push/pull first then fallback. Use the same logic for
+ both cases.
+
+ * daemon/gvfsbackendburn.c:
+ Port Upload to Push.
+
+ * daemon/gvfsbackendtrash.c:
+ Implement the Pull method. That should fix bug #529971
+
+2008-09-01 Christian Kellner <gicmo@gnome.org>
+
+ * monitor/hal/ghalvolume.c: (do_update_from_hal):
+ Use g_format_size_for_display for consistency.
+ Patch from Christian Persch <chpe@gnome.org>
+ Fixes bug #550100
+
+2008-08-30 Matthias Clasen <mclasen@redhat.com>
+
+ * common/gmountspec.c (g_mount_spec_from_dbus): Plug a tiny
+ memory leak.
+
+2008-08-28 David Zeuthen <davidz@redhat.com>
+
+ * monitor/proxy/gproxyvolume.c: (g_proxy_volume_mount):
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c:
+ (handle_volume_mount): Make sure we really read mount_flags and
+ use_mount_operation. Fixes RH bug 460223.
+
+2008-08-27 Bastien Nocera <hadess@hadess.net>
+
+ * client/gdaemonvfs.c (get_mountspec_from_uri),
+ (_g_daemon_vfs_get_uri_for_mountspec): Don't drop
+ query and fragment portions of the URI when decoding
+ it and the URI scheme isn't handled by any backends
+ (Closes: #549553)
+
+2008-08-25 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 549253 – error path leaks
+
+ * common/gmountoperationdbus.c:
+ * common/gdbusutils.c:
+ * daemon/gvfsbackendgphoto2.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsjobsetattribute.c: Plug some leaks on
+ error paths.
+
+2008-08-25 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackenddav.c (ms_response_to_file_info):
+ Same as below but for the webdav's getlastmodified
+ response (Closes: #538573)
+
+2008-08-22 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendhttp.c (query_info_ready): Use
+ libsoup to parse the "Last-Modified" header, not
+ the ISO-8601 parsing functions (Closes: #547133)
+ Requires libsoup trunk
+
+2008-08-21 Hans Petter Jansson <hpj@novell.com>
+
+ * daemon/gvfsbackendgphoto2.c (ensure_ignore_prefix)
+ (do_mount)
+ (do_enumerate): Improve various user- and translator-
+ unfriendly error messages.
+
+2008-08-21 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Late post-release version bump to 0.99.6.
+
+2008-08-21 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * daemon/gvfsbackendgphoto2.c (do_unmount):
+ Handle plural forms correctly. Fixes bug #548841.
+
+=== gvfs 0.99.5 ===
+
+2008-08-16 Jesse van den Kieboom <jesse@icecrew.nl>
+
+ * daemon/gvfsbackenddav.c:
+ Fixed using display_name property getting overwritten
+
+2008-08-16 Christian Neumair <cneumair@gnome.org>
+
+ * daemon/gvfsbackendtrash.c (add_extra_trash_info):
+ Correctly set copy name to original file name. Fixes #41852.
+
+2008-08-07 Jesse van den Kieboom <jesse@icecrew.nl>
+
+ * client/gdaemonfileoutputstream.c:
+ Fixed crash in gio because error was not properly
+ being set in the query_info noop
+
+2008-08-05 Jesse van den Kieboom <jesse@icecrew.nl>
+
+ * daemon/gvfsbackendsftp.c:
+ Added restoring file permissions when replacing a file.
+
+2008-08-05 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonfile.c:
+ Remove wrong dbus reply struct checks for replace_async,
+ create_async and append_async that would live to (false)
+ invalid reply errors.
+
+2008-08-05 Jesse van den Kieboom <jesse@icecrew.nl>
+
+ * client/gdaemonfile.c:
+ Set etag to "" when supplied to g_daemon_file_replace_async
+ with NULL. Bug #546300
+
+2008-08-05 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac: Post-release bump to 0.99.5.
+
+=== gvfs 0.99.4 ===
+
+2008-08-05 Christian Kellner <gicmo@gnome.org>
+
+ * NEWS: Update for release
+
+2008-08-05 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac:
+ Require glib 2.17.6 (cause by GEmblemedIcon changes)
+
+2008-08-05 Christian Kellner <gicmo@gnome.org>
+
+ * monitor/hal/ghaldrive.c:
+ Various ref counting fixes.
+
+ * monitor/hal/ghalvolume.c:
+ Report error in idle to avoid calling a callback with the
+ volume lock held.
+ Use volume lock in hhal_volume_get_activation_root. Various
+ ref counting fixes.
+
+ Bug #545489. Based on a patch from Matthias Clasen.
+
+2008-08-04 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonfile.c: (g_daemon_file_replace_async):
+ Correctly set the mode to 2 resulting in the replace vfunc being
+ called inside the backends.
+ Bug #544008. Patch by Jesse van den Kieboom <jesse@icecrew.net>
+
+2008-08-04 Matthias Clasen <mclasen@redhat.com>
+
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c:
+ * monitor/proxy/gproxyvolumemonitor.c: Update the GIcon serialization
+ code to work with GEmblem.
+
+2008-08-03 Christian Kellner <gicmo@gnome.org>
+
+ * client/gvfsfusedaemon.c:
+ Avoid a race between the subthread and the main thread in the case
+ of dbus going bye-bye.
+ Bug #543552. Patch from Austin Lund <austin.lund@gmail.com>
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonvfs.c:
+ Make sure we handle URI schemes case insensitive, so that File://
+ and other versions also work. Bug #528891
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendtrash.c: Don't include internal mounts
+ while building up the list of trash directories. Bug #525779
+ Patcg from A. Walton <awalton@svn.gnome.org>
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c: (parse_xml): Free the xml doc in
+ error cases. Plug the leaks, fix bug #545968, thanks to
+ Christian Persch <chpe@gnome.org> again!
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Use XML_PARSE_NONET with xmlReadMemory when parsing the webdav
+ responses to disallow net access of the parser. Bug #545966
+ Patch by Christian Persch <chpe@gnome.org>
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendtrash.c: (list_trash_dirs):
+ Create the home trash directory if it doesn't already exist,
+ so that we can monitor it for changes. Part two of bug #509740;
+ Patch by Hans Petter Jansson <hpj@novell.com>
+
+2008-08-02 Christian Kellner <gicmo@gnome.org>
+
+ * autogen.sh: Allow libtool 2.2.
+
+2008-08-02 Christian Persch <chpe@gnome.org>
+
+ * ChangeLog
+ * client/gdaemonfile.c
+ * client/gdaemonfileinputstream.c
+ * client/gdaemonfileoutputstream.c
+ * client/gvfsdaemondbus.c
+ * common/gdbusutils.c
+ * common/gvfsdaemonprotocol.c
+ * daemon/gvfsbackendarchive.c
+ * daemon/gvfsbackendcdda.c
+ * daemon/gvfsbackenddav.c
+ * daemon/gvfsbackendftp.c
+ * daemon/gvfsbackendgphoto2.c
+ * daemon/gvfsbackendobexftp-cap-parser.c
+ * daemon/gvfsbackendobexftp-fl-parser.c
+ * daemon/gvfsbackendobexftp.c
+ * daemon/gvfsbackendsftp.c
+ * daemon/gvfsbackendsmb.c
+ * daemon/gvfsbackendsmbbrowse.c
+ * daemon/gvfsjob.c
+ * daemon/gvfsjobopenforwrite.c
+ * daemon/gvfsreadchannel.c
+ * daemon/gvfswritechannel.c
+ * daemon/mount.c
+ * daemon/soup-input-stream.c
+ * daemon/soup-output-stream.c: Use g_set_error_literal where
+ appropriate. Bug #539167.
+
+2008-07-29 David Zeuthen <davidz@redhat.com>
+
+ * client/gdaemonmount.c:
+ * common/gmounttracker.c:
+ * common/gmounttracker.h:
+ * daemon/gvfsbackend.c:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsbackendcdda.c:
+ * daemon/gvfsbackendgphoto2.c:
+ * daemon/mount.c:
+ Add x-content/* support to daemon mounts. Right now a backend
+ can only set the x-content/* type ahead of time. We might want
+ to add support dynamically obtaining it too (e.g. support
+ force_rescan).
+
+ * monitor/hal/ghalmount.c:
+ * monitor/hal/ghalvolume.c:
+ * monitor/hal/ghalvolumemonitor.c:
+ * monitor/hal/hal-utils.c:
+ * monitor/hal/hal-utils.h:
+ Add x-content/* support to the HAL volume monitor.
+
+ * monitor/proxy/gproxymount.c:
+ * monitor/proxy/gproxymount.h:
+ * monitor/proxy/gproxyvolumemonitor.c:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c:
+ Add x-content/* support to proxy volume monitor. Also fix
+ a number of bugs the initial implementation had.
+
+ * programs/gvfs-mount.c:
+ Print out x-content-types.
+
+2008-07-28 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 528848 – [PATCH] statfs lies
+
+ * client/gvfsfusedaemon.c (vfs_statfs): Don't call
+ statvfs on /. Patch by Bill Nottingham.
+
+2008-07-28 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 518284 – need to add i18n on module branching
+
+ * daemon/gvfsbackendcdda.c:
+ * daemon/gvfsbackendgphoto2.c:
+ * daemon/gvfsbackendobexftp.c: Now is later.
+ Remove the I18N_LATER hack.
+
+2008-07-28 Matthias Clasen <mclasen@redhat.com>
+
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c (append_mount):
+ Don't pass a NULL uuid to dbus_message_iter_append_basic. Fixes
+ a crash with bind mounts.
+
+2008-07-28 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 545068 – use standard icon names
+
+ * daemon/gvfsbackendburn.c:
+ * daemon/gvfsbackendcomputer.c:
+ * daemon/gvfsbackenddnssd.c: Use standard icon names.
+
+2008-07-28 Matthias Clasen <mclasen@redhat.com>
+
+ * configure.ac: Bump GLib requirement to 2.17.5 (for GEmblemedIcon)
+ * gproxyvolumemonitor.c: Handle GEmblemedIcon in deserialization code.
+ * gvfsproxyvolumemonitordaemon.c: Handle GEmblemedIcon in
+ serialization code.
+
+2008-07-23 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Post-release bump to 0.99.4.
+
+=== gvfs 0.99.3 ===
+
+2008-07-23 Hans Petter Jansson <hpj@novell.com>
+
+ * NEWS: 0.99.3 update.
+
+2008-07-23 David Zeuthen <davidz@redhat.com>
+
+ * monitor/proxy/gproxyvolumemonitor.c
+ (g_proxy_volume_monitor_finalize): Fix crasher (#544399)
+
+2008-07-22 Matthias Clasen <mclasen@redhat.com>
+
+ * configure.ac: Post-release bump
+
+=== gvfs 0.99.2 ===
+
+2008-07-22 Matthias Clasen <mclasen@redhat.com>
+
+ * Makefile.am: Fix up intltool mess
+ * configure.ac: Bump glib requirement to 2.17.4
+ * NEWS: Updates
+
+2008-07-21 David Zeuthen <davidz@redhat.com>
+
+ * monitor/gphoto2/ggphoto2volume.c (do_update_from_hal_for_camera):
+ * daemon/gvfsbackendgphoto2.c (compute_icon_name):
+ (find_udi_for_device):
+ Use 'camera-photo' rather than just 'camera' since gnome-icon-theme
+ in 2.23/2.24 no longer ships 'camera'. Now the icons look fine again.
+
+2008-07-21 David Zeuthen <davidz@redhat.com>
+
+ * configure.ac:
+ * monitor/Makefile.am:
+ * monitor/hal/*:
+ * monitor/gphoto2/*:
+ Separate the hal and gphoto2 volume monitors - this is in part
+ needed to solve bug #520123.
+
+2008-07-21 David Zeuthen <davidz@redhat.com>
+
+ * monitor/proxy/gproxyvolumemonitor.c
+ (g_proxy_volume_monitor_setup_session_bus_connection): Use the
+ correct hash functions for the hash table of existing proxy
+ volume monitors
+
+2008-07-21 Kjartan Maraas <kmaraas@gnome.org>
+
+ * monitor/proxy/gvfsproxyvolumemonitordaemon.c:
+ #include <locale.h> to fix the build.
+
+2008-07-19 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gdaemonfile.c (g_daemon_file_set_attribute): Don't leak
+ D-Bus messages.
+
+2008-07-18 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c (vfs_open)
+ (vfs_create): Hold the file handle lock while opening the stream.
+ Second part of fix for #536614.
+
+2008-07-17 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c (reindex_file_handle_for_path): Steal the
+ old file handle record from the global hash table before replacing
+ its path, not after. Part of fix for #536614.
+
+2008-07-16 David Zeuthen <davidz@redhat.com>
+
+ * monitor/proxy/gproxyvolumemonitor.c:
+ * monitor/proxy/gproxyvolumemonitor.h:
+ * monitor/proxy/remote-volume-monitor-module.c:
+ Avoid setting up proxy volume monitors if no session bus is
+ available. Fixes a crasher with the Fedora NetworkManager system
+ settings plug-in that is now using GIO to do file monitoring.
+
+2008-07-08 David Zeuthen <davidz@redhat.com>
+
+ * monitor/hal/Makefile.am: Fix 'make distcheck'.
+
+2008-07-08 David Zeuthen <davidz@redhat.com>
+
+ * configure.in:
+ * Makefile.am:
+ * hal/*:
+ * monitor/Makefile.am:
+ * monitor/hal/*:
+ Move hal/ to monitor/hal/.
+
+2008-07-08 David Zeuthen <davidz@redhat.com>
+
+ Provide infrastructure for out of process volume monitors and
+ port the hal volume monitor to use it (#520132).
+
+ * Makefile.am:
+ * configure.ac:
+ Add the monitor and monitor/proxy directories.
+
+ * hal/Makefile.am:
+ Don't build a gio module for the hal volume monitor; instead
+ build a volume monitor daemon.
+
+ * hal/ghaldrive.[ch]:
+ * hal/ghalmount.[ch]:
+ * hal/ghalvolume.[ch]:
+ * hal/ghalvolumemonitor.[ch]:
+ * hal/hal-device.[ch]:
+ * hal/hal-device.[ch]:
+ * hal/hal-pool.[ch]:
+ Make all types static and implement g_volume_get_activation_root()
+ added to gio (#541793). Also emit the drive-eject-button
+ signal (#541794).
+
+ * hal/hal-module.c:
+ Removed since the monitor is being moved out of process.
+
+ * hal/hal-volume-monitor-daemon.c:
+ * hal/hal.monitor:
+ * hal/org.gtk.Private.HalVolumeMonitor.service.in:
+ New files for remote volume monitor.
+
+ * monitor/Makefile.am:
+ New file.
+
+ * monitor/proxy/*:
+ Add proxy volume monitor gio module (the D-Bus client side of
+ out-of-process volume monitors) and a static library for providing
+ the D-Bus server side of out of process volume monitors.
+
+ * programs/gvfs-mount.c:
+ Print activation uri for a volumes and icons for drives.
+ Also unref volume monitor when no longer in use.
+
+2008-07-01 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac: Correctly check the right libhal for hal features.
+ Patch from Andreas Rottmann <a.rottmann@gmx.at> (#537149)
+
+2008-06-16 Ross Burton <ross@burtonini.com>
+
+ Bug 536252 – GFileEnumerator should allow access to the containing
+ GFile
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileenumerator.c:
+ * client/gdaemonfileenumerator.h:
+ Pass the GFile to the file enumerator constructor and use it to
+ set the container property. (Requires glib r7044)
+
+2008-06-11 Ross Burton <ross@burtonini.com>
+
+ * programs/gvfs-mkdir.c:
+ Add -p to create parents (using
+ g_file_make_directory_with_parents, just landed in glib). Patch
+ from A Walton (#511367)
+
+2008-06-11 A. Walton <awalton@gnome.org>
+
+ * daemon/gvfsbackendtrash.c (escape_pathname), (unescape_pathname):
+ Use hex escapes in the trash backend.
+ Patch by Andreas Henriksson.
+ Fixes bug #523139.
+
+2008-06-11 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendftp.c:
+ Fix recursive copy of directories (#522933)
+ Introduce new error 550 handling framework
+
+2008-06-10 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendarchive.c: (gvfs_archive_pop_job):
+ * daemon/gvfsbackenddav.c: (stat_location), (write_ready),
+ (close_write_ready), (do_make_directory), (do_delete):
+ * daemon/gvfsbackendftp.c:
+ (ftp_connection_set_error_from_response):
+ * daemon/gvfsbackendhttp.c: (g_vfs_job_failed_from_http_status),
+ (open_for_read_ready), (read_ready), (try_seek_on_read),
+ (close_read_ready):
+ * daemon/gvfsbackendobexftp.c: (_query_file_info_helper),
+ (error_occurred_cb), (do_delete):
+ Fix build warnings with GCC 4.3.0 (#537588).
+ * daemon/gvfsjob.c: (g_vfs_job_failed), (g_vfs_job_failed_literal):
+ * daemon/gvfsjob.h:
+ Add g_vfs_job_failed_literal ().
+
+2008-06-09 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp-fl-parser.c (fl_parser_start_node_cb):
+ Patch from Tomáš Bžatek <tbzatek@redhat.com> to fix the fugly icons
+ when the mime-type of a file isn't known to us. See:
+ https://bugzilla.redhat.com/show_bug.cgi?id=450453
+
+2008-06-04 Bastien Nocera <hadess@hadess.net>
+
+ * hal/ghalvolumemonitor.c (update_cameras): Don't add
+ devices that are both audio players and cameras twice,
+ as it causes 1) error messages when plugging in (it tries to
+ mount the device another time) 2) weird behaviour in
+ nautilus' computer:/ (See #536601)
+
+2008-06-03 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Post-release bump to 0.99.2.
+
+=== gvfs 0.99.1 ===
+
+2008-06-03 Hans Petter Jansson <hpj@novell.com>
+
+ * NEWS: Prepare for 0.99.1 release.
+
+2008-06-03 Hans Petter Jansson <hpj@novell.com>
+
+ * configure.ac: Fix definition of giomodulesdir, so we install
+ GIO modules to the libdir specified by the user. Fixes distcheck.
+
+2008-05-28 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c: (do_open_for_read):
+ Return G_IO_ERROR_IS_DIRECTORY when attempting
+ to read a directory (fixes #522933 for SMB)
+
+2008-05-27 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c: (do_mount):
+ Don't set domain to mountspec when not setting username
+
+2008-05-27 Tomas Bzatek <tbzatek@redhat.com>
+
+ * common/gmountspec.c: (add_item):
+ Don't allow setting a null parameter in mountspec (coming
+ from broken backend)
+
+2008-05-22 Hans Petter Jansson <hpj@novell.com>
+
+ Fix fuse daemon locking and file handle life-cycle issues that
+ were causing frequent crashes.
+
+ * client/gvfsfusedaemon.c (file_handle_new): Add a "path" field
+ pointing to a string representing the path this file handle is
+ associated with, for reverse mapping.
+ (file_handle_unref): Is now responsible for decrementing the ref
+ count and freeing the handle if it reaches 0. Note that we need
+ to check the ref count again after obtaining the global mutex.
+ (file_handle_free): The new path member is freed here.
+ (get_file_handle_for_path): Ref the obtained handle.
+ (get_or_create_file_handle_for_path): Ditto, and hold the lock the
+ whole time.
+ (reindex_file_handle_for_path): Steal the old entry to avoid
+ buildup of stale handles.
+ (free_file_handle_for_path): Remove.
+ (vfs_getattr): Unref the handle when we're done with it.
+ (vfs_rename): Ditto.
+ (vfs_unlink): Ditto.
+ (vfs_truncate): Ditto.
+ (vfs_open): Don't ref the obtained handle; it's done in the helper.
+ (vfs_create): Ditto.
+ (vfs_release): Let file_handle_unref() free the handle if
+ appropriate. Note that the old logic here was inverted, meaning we'd
+ try to free the handle if the ref count was non-zero.
+ (vfs_init): The hash table no longer owns the path key strings -
+ the file handle does.
+
+2008-05-22 Hans Petter Jansson <hpj@novell.com>
+
+ A more complete fix for GNOME bug #531516.
+
+ * client/gvfsfusedaemon.c (subthread_main): Send SIGHUP to the
+ main thread just before subthread exits.
+ (dbus_filter_func): When gvfsd goes away, exit the subthread's
+ main loop instead of immediately sending SIGHUP to parent thread.
+ Do the same when the session bus goes away.
+ (shutdown_on_idle): Remove, no longer needed.
+ (shutdown_signal): Remove, no longer needed.
+ (vfs_init): Tell dbus to not exit when session bus goes down.
+ Don't catch signals anymore, since Fuse does this for us.
+
+2008-05-22 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendarchive.c:
+ Improve error handling allowing to mount non-standard ISO images
+
+2008-05-22 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c (shutown_on_idle)
+ (shutdown_signal)
+ (vfs_init): When the process receives one of the HUP, TERM or
+ INT signals, shut down gracefully. Fixes GNOME bug #531516.
+
+2008-05-21 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c: (do_mount):
+ Fix username & domain tests while setting mount spec
+
+2008-05-21 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendsmb.c (do_mount):
+ Add GVFS_SMB_DEBUG env variable to control smb debugging.
+
+2008-05-21 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendsmb.c (do_mount):
+ Set the information on the mount spec *after* having asked
+ the user for credentials since username and domain can be
+ changed by the user.
+
+2008-05-21 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac:
+ Check for gphoto2 versions greaten then 2.4.0. Patch from
+ Tom Parker <palfrey@tevp.net>. Fixes #531702
+
+2008-05-20 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac:
+ * programs/Makefile.am:
+ Allow to disable the installation of the bash completion
+ scripts. Also make it possible to choose the directory
+ where the file gets installed. Fixes #530772
+
+2008-05-20 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp-fl-parser.c (fl_parser_fill_file_info):
+ Fill in the display name, even if layers above should be able to do
+ without (Closes: #523699)
+
+2008-05-11 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gvfsfusedaemon.c: Fix erroneous copyright header and
+ provide a better description of the source file.
+
+2008-05-09 Federico Mena Quintero <federico@novell.com>
+
+ http://bugzilla.gnome.org/show_bug.cgi?id=532375 - Fix strdup() /
+ g_free() confusion.
+
+ * hal/hal-device.c (hal_device_new_from_udi_and_properties):
+ g_strdup() the UDI. We can't just steal it, since it comes from
+ libhal, which uses strdup() (and we do g_free() in our finalizer).
+
+ * hal/hal-pool.c (hal_pool_new): Free the actual device strings here.
+
+2008-04-22 Benjamin Otte <otte@gnome.org>
+
+ * */*.[ch]: get rid of modelines
+ The modelines were inconsistent and caused issues when used in
+ different editors.
+
+2008-04-21 Sebastien Bacher <seb128@ubuntu.com>
+
+ * daemon/gvfsbackendftp.c: (do_enumerate_directory):
+ remove trailing '\r', that workarounds a parser issue causing
+ some filenames to not be listed (#524880)
+
+2008-04-21 Matthias Clasen <mclasen@redhat.com>
+
+ * client/gdaemonvfs.c:
+ * hal/hal-pool.c: Set exit-on-disconnect to FALSE on private
+ dbus connections to prevent unexpected exits. (#528785)
+
+2008-04-21 David Zeuthen <davidz@redhat.com>
+
+ * client/gvfsfusedaemon.c: Fix some reference issues, see
+ http://mail.gnome.org/archives/gvfs-list/2008-April/msg00017.html
+
+2008-04-20 David Zeuthen <davidz@redhat.com>
+
+ * daemon/gvfsbackendarchive.c: some minor fixes (#528950)
+
+2008-04-16 David Zeuthen <davidz@redhat.com>
+
+ * hal/ghalvolumemonitor.c: (should_mount_be_ignored),
+ (should_volume_be_ignored), (update_mounts):
+
+ Avoid having GVolume and GMount objects for mounts for which the
+ mount point will make g_unix_mount_guess_should_display() return
+ FALSE. This fixes a problem where e.g. live cd installers mounts
+ some file system somewhere (e.g. a /boot partition at
+ /mnt/installer_boot).
+
+2008-04-16 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 526793 – unmount hangs with some backends
+
+ * daemon/gvfsbackendgphoto2.c: Set exit-on-disconnect to FALSE
+ on the private dbus connection to prevent unexpected exit before
+ the job is done.
+
+2008-04-16 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Set mount prefix on the mount_spec (again). Fixes #528218
+
+2008-04-16 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendhttp.c:
+ Add logging for soup so we can get easy network traces even
+ if we are doing https.
+
+2008-04-15 Matthias Clasen <mclasen@redhat.com>
+
+ Bug 526454 – too early use of dbus session bus
+
+ * client/gdaemonvfs.c (g_io_module_load): Refuse to load if
+ there is no session bus.
+
+2008-04-14 Matthias Clasen <mclasen@redhat.com>
+
+ * client/gvfsfusedaemon.c: You cannot store pointers in integers.
+ Fixes a crash on 64bit systems.
+
+2008-04-14 Matthias Clasen <mclasen@redhat.com>
+
+ * common/gmounttracker.c (g_mount_tracker_finalize): Only free
+ lock if it is non-NULL. Pointed out by Denis Leroy.
+
+2008-04-07 David Zeuthen <davidz@redhat.com>
+
+ * hal/ghalvolume.c (g_hal_volume_new): Unbreak the gphoto2 backend
+ by allowing automounting.
+
+ * programs/gvfs-mount.c (main, unmount_all_with_scheme): Add a
+ new option --unmount-scheme
+
+ * AUTHORS: Add cdda and gphoto2 backends
+
+2008-04-05 Christian Kellner <gicmo@gnome.org>
+
+ * client/httpuri.c:
+ Only set a port in the mount spec if it is not the default
+ port for the scheme.
+
+ * daemon/gvfsbackenddav.c:
+ Cleanup mount function a bit.
+
+2008-04-04 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Implement set_display_name. (#525980)
+ With this patch we also do our own redirection handling which
+ alyways allows redirects from /a/b -> /a/b/ (trainling slashes)
+ even for non safe methods. Also some code was cleaned up.
+
+2008-04-02 Christian Kellner <gicmo@gnome.org>
+
+ * hal/hal-utils.h:
+ * hal/hal-utils.c:
+ Create new files for utility functions and move get_disc_icon()
+ and get_disc_name() here.
+ Also create get_themed_icon_with_fallbacks() to create
+ GThemedIcons with default fallbacks but with the ability to
+ pass in another name to create the fallbacks from then the
+ icon name.
+
+ * hal/ghalmount.c:
+ * hal/ghalvolume.c:
+ Use newly created get_themed_icon_with_fallbacks () and pass
+ in custom fallback name for encrypted mounts/volumes (#525153).
+
+ * hal/Makefile.am:
+ Add hal-utils.[hc]
+
+ * programs/gvfs-mount.c:
+ Display the icon names for mounts/volumes if the icon is
+ a GThemedIcon.
+
+ [Merged from gnome-2-22]
+
+2008-04-01 Sebastien Bacher <seb128@ubuntu.com>
+
+ * hal/ghalmount.c: (format_size_for_display), (do_update_from_hal):
+ Use consistent translatable strings for mounts and volume (#525286)
+
+2008-03-31 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Get the right size of the command messages.
+ Actually send file attributes in mkdir request.
+
+2008-03-31 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendsftp.c: Make sure we send (error)
+ replies to all outstanding jobs and unmount the mount
+ in case of an error occures while reading data from
+ the pipe to the ssh agent (e.g. if the ssh process died).
+
+2008-03-31 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsdaemondbus.[ch]:
+ In call_sync, on stale cache errors due to a
+ mount daemon disappearing, invalidate caches and
+ return G_VFS_ERROR_RETRY so that the caller can
+ retry with fresh caches.
+
+ * client/gdaemonfile.c:
+ Retry calls on G_VFS_ERROR_RETRY.
+
+2008-03-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_pop_job):
+ fix race that could cause uploads to stop
+
+2008-03-28 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Bump version to 0.99.1 for unstable development
+ Stable branch is gnome-2-22
+
+2008-03-28 Paolo Borelli <pborelli@katamail.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsjobclosewrite.c:
+ Plug some more minor memory leaks.
+
+2008-03-28 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.2.2 ===
+
+2008-05-09 Federico Mena Quintero <federico@novell.com>:ChangeLog
+
+2008-03-28 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am (gvfsd_smb_SOURCES):
+ Dist libsmb-compat.h.
+
+ * NEWS:
+ Update for release
+
+2008-03-28 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac: Silence out libtool if
+ make is invoked with --silence.
+
+2008-03-28 Paolo Borelli <pborelli@katamail.com>
+
+ * daemon/gvfsbackendtrash.c: plug some minor memory leaks.
+
+2008-03-28 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileenumerator.c (g_daemon_file_enumerator_next_file):
+ Actually increment count so that timeouts works.
+ Pointed out by Joe Marcus Clarke
+
+2008-03-27 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Handle all target exists errors correctly
+ in move. This should make us not silently
+ overwrite files.
+
+ * daemon/gvfsjobmove.[ch]:
+ Add g_vfs_job_move_progress_callback
+
+2008-03-27 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Introduce helpers for multi-request ops.
+ Use it for query_info.
+
+2008-03-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ Implement true async query_filesystem_info
+
+2008-03-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileenumerator.c:
+ (g_daemon_file_enumerator_next_file):
+ Avoid hanging forever and not sending any async messages.
+ This could happen if we raced and missed the done check.
+
+2008-03-26 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsmonitor.c:
+ Send replies to subscribe and unsubscribe messages.
+
+2008-03-26 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Pass id via the command object, not via out parameter.
+ Removes a bunch of code to pass the id around.
+
+2008-03-25 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfschannel.c: (got_request), (send_reply_cb):
+ Do not create new read/write jobs if the gvfschannel has been
+ cancelled. Fixes a crash in sftp backend (#522192).
+
+2008-03-25 Paolo Borelli <pborelli@katamail.com>
+
+ * daemon/gvfsbackendtrash.c (add_extra_trash_info):
+ Make sure the display name is correct even for subdirectories
+ inside the trash. (#523127)
+
+2008-03-25 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendarchive.c (archive_file_set_info_from_entry):
+ Better mount icons and root display name.
+
+2008-03-24 A. Walton <awalton@svn.gnome.org>
+
+ * configure.ac:
+ The CDDA backend requires HAL to build.
+ Closes bug #524062.
+
+2008-03-22 Christian Kellner <gicmo@gnome.org>
+
+ * client/Makefile.am:
+ * configure.ac:
+ * gconf/Makefile.am:
+ * hal/Makefile.am:
+ Respect the giomoduledir provided in gio's package config
+ file. (#523852 and maybe #523039)
+
+2008-03-20 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/libsmb-compat.h:
+ Port to new smbclient API introduced in samba-3.2.0pre2
+
+2008-03-19 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsjobenumerate.c (send_reply):
+ * daemon/gvfsjobdbus.c (send_reply):
+ Add job pointer to output spew to make it possible
+ to match lines.
+
+2008-03-19 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * daemon/gvfsbackendsftp.c: (handle_login): Make the sftp backend
+ work when pam_krb5 is used on the server side.
+
+2008-03-18 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac: Post release version bump.
+
+=== gvfs 0.2.1 ===
+
+2008-03-17 Christian Kellner <gicmo@gnome.org>
+
+ * NEWS: Update for release
+
+2008-03-17 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendftp.c (do_mount):
+ Correctly handle username in mountspec. Only set it if
+ it was in the requested mountspec (and only to that value).
+ Fixes #522449
+
+2008-03-17 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonfile.c: (find_enclosing_mount_cb): Don't unref
+ mount_info since we don't one a ref. (#522919)
+
+2008-03-17 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ return G_IO_ERROR_NOT_EMPTY if we're trying to delete a non-empty
+ directory.
+ * hal/ghalvolumemonitor.c: (get_mount_point_for_device):
+ remove unused variable
+
+2008-03-16 Christian Kellner <gicmo@gnome.org>
+
+ * AUTHORS: Forgot to mention A. Walton. Correct that.
+
+2008-03-16 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonfile.c: Don't free up the error that
+ we don't own (#522566). Thanks Cosimo Cecchi for helping
+ to debug the issue.
+
+2008-03-16 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * programs/gvfs-rename.c (main): Fix wording of error
+ messages. Don't include "Error renaming file" since
+ that's what the error->message might contain as well.
+
+2008-03-14 Christian Kellner <gicmo@gnome.org>
+
+ * programs/Makefile.am:
+ * programs/gvfs-rename.c:
+ Add a little helper program that renames files
+ by calling g_file_set_display_name ().
+
+2008-03-14 Christian Kellner <gicmo@gnome.org>
+
+ * AUTHORS: Update, add a lot of people and I am
+ sure I have forgotten a few.
+
+ * MAINTAINERS: Add myself
+
+2008-03-14 Hans Petter Jansson <hpj@novell.com>
+
+ Implement most of the GDaemonFile async functions.
+
+ * client/gdaemonfile.c (stream_open_cb): Implement.
+ (append_to_async_cb): Implement.
+ (g_daemon_file_append_to_async): Implement.
+ (g_daemon_file_append_to_finish): Implement.
+ (create_async_cb): Implement.
+ (g_daemon_file_create_async): Implement.
+ (g_daemon_file_create_finish): Implement.
+ (enumerate_children_async_cb): Implement.
+ (g_daemon_file_enumerate_children_async): Implement.
+ (g_daemon_file_enumerate_children_finish): Implement.
+ (find_enclosing_mount_cb): Implement.
+ (g_daemon_file_find_enclosing_mount_async): Implement.
+ (g_daemon_file_find_enclosing_mount_finish): Implement.
+ (replace_async_cb): Implement.
+ (g_daemon_file_replace_async): Implement.
+ (g_daemon_file_replace_finish): Implement.
+ (set_display_name_async_cb): Implement.
+ (g_daemon_file_set_display_name_async): Implement.
+ (g_daemon_file_set_display_name_finish): Implement.
+ (g_daemon_file_file_iface_init): Hook up new async functions.
+
+2008-03-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/main.c:
+ Don't autostart fuse backend if the GVFS_DISABLE_FUSE
+ env var is set
+
+2008-03-14 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolume.c (g_hal_volume_new):
+ Respect storage.automount_enabled_hint hal property (#520736)
+ Patch from Martin Pitt
+
+2008-03-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ (set_info_from_stat):
+ Mark files with an initial dot to be hidden.
+ This handles unix smb shares, and should not affect
+ windows shares much, since they generally don't use dot
+ for extensions so its not used otherwise in filenames.
+
+2008-03-14 Christian Kellner <gicmo@gnome.org>
+
+ * client/httpuri.c:
+ Make sure we set the port to -1 in case when no port
+ is specified on the url so the port will be omiited
+ when we convert the url to a string
+
+2008-03-13 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/archive.mount.in:
+ Actually add the mount file for archive
+
+2008-03-12 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ fix enumerating to do the right thing
+
+2008-03-12 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendarchive.[ch]:
+ Added archive backend from Benjamin Otte
+ Requires libarchive
+
+2008-03-12 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ invalidate the cache of directories that we modified ourselves.
+ * daemon/Makefile.am:
+ allow 10 threads in parallel
+
+2008-03-12 Hans Petter Jansson <hpj@novell.com>
+
+ * client/gdaemonfile.c (do_async_path_call): We were testing the
+ wrong cancellable pointer for non-NULL-ness, which broke cancellation
+ for all async operations. Fix that.
+
+2008-03-11 Alexander Larsson <alexl@redhat.com>
+
+ * common/gsysutils.c:
+ * configure.ac:
+ OpenBSB portability fixes.
+ Patch from Jasper Lievisse Adriaanse <jasper@humppa.nl>
+
+2008-03-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c (spawn_ssh):
+ Use GError->message, not GError->msg.
+ Patch from Jasper Lievisse Adriaanse <jasper@humppa.nl>
+
+2008-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.2.0.1 ===
+
+2008-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Bump version to 0.2.0.1 (minor release
+ last translation changes)
+
+2008-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+ * configure.ac:
+ Bump version to 0.2.0
+
+2008-03-10 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ Free strings with g_free, not dbus_free (#521269)
+
+2008-03-08 Christian Kellner <gicmo@gnome.org>
+
+ * hal/ghalmount.c:
+ Use dgettext instead of gettext as we are a library.
+
+ * hal/ghalvolume.c:
+ Translate disc names (using dgettext).
+
+2008-03-07 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ (get_mount_point_for_device):
+ (should_volume_be_ignored):
+ Really make sure we ignore stuff outside /media (#520851)
+
+2008-03-07 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalmount.c:
+ (get_disc_name):
+ Translate disc names.
+
+ * hal/ghalvolume.c:
+ (g_hal_volume_new):
+ Don't automount gphoto volumes.
+
+2008-03-07 Kjartan Maraas <kmaraas@gnome.org>
+
+ * programs/gvfs-mount.c: ANSIfication
+ * daemon/gvfsbackendnetwork.c: Same.
+
+2008-03-07 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/soup-input-stream.c: Since G_SEEK_END is not supported
+ at the moment immediately return FALSE without aborting the
+ the soup message.
+
+2008-03-07 Kjartan Maraas <kmaraas@gnome.org>
+
+ * daemon/gvfsreadchannel.c,
+ * daemon/gvfswritechannel.c:
+ Fix format specifiers here.
+
+2008-03-07 Kjartan Maraas <kmaraas@gnome.org>
+
+ * client/httpuri.c: Remove unused vars.
+ * daemon/gvfsbackenddav.c: Remove a couple
+ of unused variables.
+
+2008-03-07 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Initialize error variable to NULL. (#519035)
+
+2008-03-06 David Zeuthen <davidz@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ (_g_unix_mount_point_guess_should_display),
+ (should_be_hidden_according_to_etc_fstab),
+ (should_volume_be_ignored), (should_drive_be_ignored),
+ (update_drives), (update_volumes):
+ Avoid showing volumes from /etc/fstab if the mount point is one
+ that should not be displayed to the user (#520851)
+
+2008-03-07 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Only ask for common properties and don't use allprop.
+
+2008-03-06 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Correctly set the content types and the icon correclty. (#518679)
+ Also don't add the If-None-Matcher header for now since
+ early apache versions don't like it. We need to be smart about
+ that later.
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * common/gsysutils.c:
+ Include <sys/types.h> also (#520307)
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ Use g_content_type_get_icon() instead of open
+ coding it. Also picks up more icons since
+ that has been fixed. (#520742)
+
+2008-03-06 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_create),
+ (ftp_connection_ensure_data_connection),
+ (g_vfs_backend_ftp_pop_connection), (do_mount):
+ timeout I/O or g_cond_wait after 30 seconds
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * common/gsysutils.c:
+ * configure.ac:
+ Include sys/uio.h if availible (#520307)
+
+2008-03-06 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ fail early if there's no ftp server where we connect
+
+2008-03-06 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_system),
+ (ftp_connection_use), (dir_default_iter_process):
+ parse the ftp server's system. Using that information, mark dot-files
+ as hidden.
+ Fixes #520203
+
+2008-03-05 A. Walton <awalton@svn.gnome.org>
+
+ * programs/gvfs-cat.c (main):
+ * programs/gvfs-copy.c (main):
+ * programs/gvfs-info.c (main):
+ * programs/gvfs-ls.c (main):
+ * programs/gvfs-move.c (main):
+ * programs/gvfs-open.c (main):
+ * programs/gvfs-save.c (main):
+ * programs/gvfs-tree.c (main):
+ Error out if the user passes invalid flags and warn the user.
+ Fixes bug #520086.
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Allow setting unix mode on sftp (#520571)
+ Patch from Carlos Garcia Campos
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackenddav.c:
+ (do_mount):
+ Set display name for dav mount (#519588)
+
+2008-03-06 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_move):
+ fail if file exists
+
+2008-03-06 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ (foreign_volume_removed):
+ Avoid deadlock when foreign volume is removed.
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (dir_default_iter_process),
+ (do_enumerate):
+ don't list "." and ".." directories.
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_create):
+ fail if the file to be created already exists
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ set anonymous login to FALSE, no uninitialized variables please.
+ * hal/ghalvolumemonitor.c: (adopt_orphan_mount):
+ fix warning due to glib changes
+
+2008-03-05 Bastien Nocera <hadess@hadess.net>
+
+ * INSTALL: Add mention of obex-data-server
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (dir_default_get_root):
+ the proper icon name is folder-remote, not remote-folder.
+ really fixed #520189
+
+2008-03-05 Bastien Nocera <hadess@hadess.net>
+
+ * configure.ac: Disable gphoto2 building when
+ HAL is disabled as well (Closes: #519872)
+
+2008-03-05 Bastien Nocera <hadess@hadess.net>
+
+ * client/gvfsuriutils.c (g_vfs_decode_uri):
+ Fix parsing of IPv6-style hostnames to not find the
+ port in the path section of the URI, fixes browing
+ browsing ObexFTP on Nokia Series 60 phones which show
+ drive letters as directories in the root (eg. "C:")
+ (Closes: #520314)
+
+ * client/test-uri-utils.c (main): Add test for the above,
+ and another test for the IPv4-style URIs
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsdaemonutils.c:
+ (gvfs_file_info_populate_content_types):
+ add text-x-generic mime type as a last fallback option.
+ Fixes #520189
+
+2008-03-05 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ rewrite file info construction and directory listing. It should now
+ correctly resolve symlinks and be fast enough for general use.
+
+2008-03-05 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (do_enumerate):
+ Better error message for Nokia 3650 phones
+
+2008-03-05 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_get_icon_from_type),
+ (_get_type_from_class), (_is_nokia_3650), (_get_device_properties),
+ (g_vfs_backend_obexftp_finalize), (do_mount), (do_open_for_read),
+ (do_query_info), (do_query_fs_info), (do_enumerate), (do_delete):
+ Error out cleanly from do_mount() if we somehow lose connection
+ to the device, Show a meaningful error when browsing broken
+ Nokia 3650 phones (Closes: #519733)
+
+2008-03-05 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountsource.c:
+ (ask_password_reply):
+ Always set password to non-NULL, but keep
+ user/domain as NULL if not specified by user.
+ Fixes #520317 (smb auth crash)
+
+2008-03-05 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ (g_daemon_mount_eject_finish):
+ Initialize drive variable not access
+ undefined memory (#520388)
+
+2008-03-04 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/ParseFTPList.c (ParseFTPList):
+ Trivial C89 patch, fixes #520339.
+ Patch from Jens Granseuer.
+
+2008-03-04 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ set the right GError here. Makes gvfsd-ftp run fine manually again.
+
+2008-03-04 Benjamin Otte <otte@gnome.org>
+
+ * common/gmountspec.c: (g_mount_spec_set_with_len):
+ add g_return_if_fail here - I had SEGVs sometime later due to values
+ being NULL here. So better catch em early
+
+2008-03-04 Sebastien Bacher <seb128@ubuntu.com>
+
+ * configure.ac: New version update
+
+=== gvfs 0.1.11 ===
+
+2008-03-04 Sebastien Bacher <seb128@ubuntu.com>
+
+ * NEWS: Update for 0.1.11
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ (g_hal_volume_monitor_finalize):
+ Free mounts with g_unix_mount_free, not g_object_unref.
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c:
+ (debug_print):
+ Actually disable debug log by default
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.10 ===
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c (_g_daemon_vfs_get_mount_info_async):
+ Bump timeout to standard gvfs time.
+ Patch from Matthias Clasen
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ (update_all):
+ Actually emit changes for volumes and mounts too
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.9 ===
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am (gvfsd_ftp_SOURCES):
+ Use correct case for ParseFTPList.h
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ (_g_daemon_vfs_get_uri_for_mountspec):
+ Fix crash with NULL host (like "ftp://")
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c (g_daemon_mount_get_icon):
+ Use fallbacks for mount icon.
+
+ * NEWS:
+ Update for release.
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c:
+ (mount_volume_from_drive):
+ Avoid crash when mounting drive
+ Fix leak.
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalmount.c:
+ Fix deadlock when looking for cdrom icons.
+
+2008-03-04 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (run_list_command):
+ don't require \r as line ending for LIST commands. Fixes ftp.netbsd.org
+ * hal/ghalvolumemonitor.c: (adopt_orphan_mount):
+ unused variable
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ * client/gdaemonvolumemonitor.c:
+ * hal/ghaldrive.c:
+ * hal/ghalmount.c:
+ * hal/ghalvolume.c:
+ * hal/ghalvolumemonitor.[ch]:
+ Properly lock around volume monitors and
+ volume monitor objects.
+ Emit all events in idles to avoid reentrancy
+ issues. Fixed deadlock in #519599.
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountsource.c:
+ * common/gmounttracker.c:
+ Work around problems with type registering when the common code
+ is used in both daemon and client.
+
+2008-03-04 Benjamin Otte <otte@gnome.org>
+
+ * common/gmountsource.c: (ask_password_reply),
+ (g_mount_source_ask_password_finish),
+ (g_mount_source_ask_password), (op_ask_password_reply):
+ * common/gmountsource.h:
+ add an anonymous_out parameter for anonymous logins.
+ * daemon/gvfsbackenddav.c: (soup_authenticate_interactive):
+ * daemon/gvfsbackendsftp.c: (handle_login):
+ * daemon/gvfsbackendsmb.c: (auth_callback):
+ make the backends compile with the new parameter. They don't use
+ anonymous logins.
+ * daemon/gvfsbackendftp.c: (do_mount):
+ make login work as users would expect it with anonymous logins.
+ Fixes bug #520131
+
+2008-03-04 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * common/gmountspec.c: (g_mount_spec_copy):
+ * daemon/gvfsdaemon.c: (g_vfs_daemon_initiate_mount):
+ * daemon/main.c: (main):
+ Fix memory leaks.
+
+2008-03-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ Avoid duplications in supported_uris.
+
+ * daemon/smb-browse.mount.in:
+ * daemon/smb.mount.in:
+ Add scheme info so smb is listed in supported_uris again.
+
+2008-03-03 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Remove unecessary message_new_from_xxx functions. Prefix all
+ public utility functions that need the backend with
+ http_backend_, i.e. rename g_vfs_backend_uri_for_filename() to
+ http_backend_uri_for_filename().
+ Create http_backend_send_message(), http_backend_queue_message()
+ convenience functions which will pick up the right SoupSession.
+
+ * daemon/gvfsbackenddav.c:
+ Port to new utility functions and http_backend_xx namespace.
+ Clean up error handling and remove the const keyword from most
+ SoupURI variables.
+
+2008-03-03 David Zeuthen <davidz@redhat.com>
+
+ Add write support to gphoto2 backend. Also performance
+ enhancements for querying, enumerating and reading.
+ Fixes bug #519651
+
+ * daemon/gvfsbackendgphoto2.c: (monitor_proxy_free), (DEBUG),
+ (write_handle_free), (ensure_not_dirty), (dup_for_gphoto2),
+ (monitors_emit_internal), (monitors_emit_created),
+ (monitors_emit_deleted), (monitors_emit_changed),
+ (caches_invalidate_all), (caches_invalidate_free_space),
+ (caches_invalidate_dir), (caches_invalidate_file),
+ (get_error_from_gphoto2), (release_device),
+ (g_vfs_backend_gphoto2_finalize), (_gphoto2_logger_func),
+ (g_vfs_backend_gphoto2_init), (find_udi_for_device),
+ (_hal_device_removed), (split_filename_with_ignore_prefix),
+ (add_ignore_prefix), (file_get_info), (is_directory), (is_regular),
+ (is_directory_empty), (ensure_ignore_prefix), (do_mount),
+ (try_mount), (do_unmount), (free_read_handle), (do_open_for_read),
+ (try_read), (try_seek_on_read), (do_close_read), (do_query_info),
+ (try_query_info), (do_enumerate), (try_enumerate),
+ (do_query_fs_info), (try_query_fs_info), (do_make_directory),
+ (do_slow_file_rename_in_same_dir), (do_file_rename_in_same_dir),
+ (do_dir_rename_in_same_dir), (do_set_display_name), (do_delete),
+ (do_create_internal), (do_create), (do_replace), (do_append_to),
+ (do_write), (do_seek_on_write), (commit_write_handle),
+ (do_close_write), (do_move), (vfs_dir_monitor_destroyed),
+ (do_create_dir_monitor), (vfs_file_monitor_destroyed),
+ (do_create_file_monitor), (g_vfs_backend_gphoto2_class_init):
+
+2008-03-03 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/mount.c: (read_mountable_config):
+ Fix memory leak.
+
+2008-03-03 Benjamin Otte <otte@gnome.org>
+
+ * client/gdaemonvfs.c: (fill_mountable_info):
+ properly parse aliases
+
+2008-03-03 Benjamin Otte <otte@gnome.org>
+
+ * client/gvfsuriutils.c: (g_vfs_decode_uri):
+ revert yesterday's commit. It broke the obex and gphoto backends. We
+ now parse hostnames different for internet hosts.
+ * daemon/ftp.mount.in:
+ Parse hostnames different.
+
+2008-03-03 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_receive),
+ (ftp_connection_sendv), (g_vfs_backend_ftp_pop_connection),
+ (do_mount):
+ fix server disconnect on timeout. Side effect is that the ftp backend
+ just spawned multiple connections support.
+
+2008-03-03 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.[ch]:
+ Add _g_dbus_message_iter_append_args_valist and
+ _g_dbus_message_iter_append_args.
+
+ * common/gvfsdaemonprotocol.h:
+ Add G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO
+
+ * client/Makefile.am:
+ * client/gdaemonvfs.c:
+ Use listMountableInfo to get supported uri schemes
+ and information for default uri handling.
+ Handle default port in uris and if host_is_inet normalize hostnames,
+ including removing ipv6 brackets.
+
+ * client/sftpuri.c:
+ Removed, as the previous work replaces it
+
+ * daemon/gvfsdaemonutils.c:
+ (gvfs_file_info_populate_content_types):
+ Fix uninitialized variable warning.
+
+ * daemon/mount.c:
+ Read new mountfile info and implement
+ list_mountable_info.
+
+ * daemon/sftp.mount.in:
+ Add info for sftp
+
+2008-03-03 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsjob.c: (g_vfs_job_try): Make sure the g_object_unref
+ call is _before_ the return call.
+ Fixes bug #519867
+
+2008-03-03 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendtrash.c: (do_mount):
+ Create the root monitor for trash when mounting. (#509740).
+
+2008-03-03 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_receive):
+ dynamically resize the read buffer. This allows receiving the huge
+ welcome messages some ftp servers think are cool.
+
+2008-03-03 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_parse_features),
+ (ftp_connection_use), (ftp_connection_ensure_data_connection):
+ implement EPSV. This should make IPv6 work.
+
+2008-03-03 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (do_mount), (do_open_for_read),
+ (do_read), (do_query_info), (do_query_fs_info), (do_enumerate),
+ (do_delete), (do_make_directory): Fix a crasher when
+ mounting fails, by not freeing the error just before using it
+ (duh!) (Closes: #519752), Fix a few error paths leaking errors
+
+2008-03-03 Luca Ferretti <elle.uca@libero.it>
+
+ * daemon/gvfsbackendftp.c: (do_query_info):
+ Make "file don't exist" message conform to other backends;
+ no, it isn't a string freeze break, the message yet exists
+ elsewhere.
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_filename_construct):
+ use g_build_path() to not get excess slashes in paths
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_try_cd), (process_line),
+ (do_query_info), (do_move), (g_vfs_backend_ftp_class_init):
+ implement move vfunc
+
+2008-03-02 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * common/gmountsource.c: (ask_password_reply):
+ Treat DBus output paramaters that contain "" as NULL. It fixes the
+ sftp backend when a username is provided by the user.
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_open_for_read), (do_start_write),
+ (do_make_directory):
+ push back connection if we fail starting a read/write
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * client/gvfsuriutils.c: (g_vfs_decode_uri):
+ don't pass the [] when parsing IPv6 addresses
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_make_directory),
+ (g_vfs_backend_ftp_class_init):
+ implement make_directory
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_delete),
+ (g_vfs_backend_ftp_class_init):
+ implement delete
+
+2008-03-02 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c:
+ redo error handling: We now store the error and the job in the
+ FtpConnection. This way we don't have to handle errors in the outer
+ functions and can just "if (conn->error) return FALSE;" in the inner
+ functions.
+
+2008-03-01 David Zeuthen <davidz@redhat.com>
+
+ * daemon/gvfsbackendcdda.c (do_mount): Avoid calling
+ cddio_cddap_close() twice on an error path.
+
+2008-03-01 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (run_list_command):
+ close the data connection before trying to receive the OK. Some
+ servers send it out only after the connection was closed properly and
+ otherwise cause stalls.
+
+2008-03-01 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ use 0 as port in the keyring when it's the default ftp port. Stops the
+ access dialog fro printing the port name.
+
+2008-03-01 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_query_file_info_helper):
+ Fix another case where the icon name was wrong for the
+ root folder (Helps: #519369)
+
+2008-03-01 Benjamin Otte <otte@gnome.org>
+
+ * daemon/Makefile.am:
+ * daemon/ParseFTPList.c:
+ * daemon/ParseFTPList.h:
+ * daemon/gvfsbackendftp.c: (ftp_connection_cd), (process_line),
+ (run_list_command), (do_query_info), (do_enumerate):
+ rewrite directory enumeration and query_info by using the LIST parsing
+ code from Mozilla. It was the only code I could find that was LGPL
+ licensed, even though it looks way out of date.
+ Also, error messages are handled way better and the code even copes
+ somewhat with symlinks.
+
+2008-02-29 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_get_icon_from_type):
+ Use better icons for the devices
+
+2008-02-29 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (_get_icon_from_type),
+ (_get_type_from_class), (_get_device_properties),
+ (do_mount): When getting the remote device's name, also get
+ its class, so we can use device specific icons instead of the
+ standard Bluetooth icon (Closes: #519369)
+
+2008-02-29 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_error_set_from_response),
+ (ftp_connection_parse_features), (ftp_filename_from_gvfs_path),
+ (ftp_filename_to_gvfs_path), (ftp_filename_construct),
+ (do_open_for_read), (do_create), (do_append), (do_replace),
+ (do_set_display_name), (g_vfs_backend_ftp_class_init):
+ introduce a differentiation between gvfs paths and ftp filenames and
+ use it. Also implement set_display_name.
+
+2008-02-29 Benjamin Otte <otte@gnome.org>
+
+ * common/gdbusutils.c: (dbus_source_add_watch):
+ * daemon/dbus-gmain.c: (connection_setup_add_watch):
+ use the right names for dbus version macros
+
+2008-02-29 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (is_connected), (do_mount),
+ (do_open_for_read), (is_busy), (do_read), (do_query_info),
+ (do_query_fs_info), (do_enumerate), (do_delete),
+ (do_make_directory): Don't use a temporary error to set
+ jobs as failed, use g_vfs_job_failed instead
+ Error out properly when trying to open a directory for read
+
+2008-02-29 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (g_vfs_backend_obexftp_finalize),
+ (_retrieve_folder_listing), (_query_file_info_helper),
+ (do_open_for_read), (do_query_info), (do_query_fs_info),
+ (do_enumerate), (do_delete): Use a convenience function
+ to load directory listings, implement a simple cache there
+ that keeps folder listings for 3 seconds (should speed up
+ folder enumeration followed by info fetching, as well
+ as checking for non-existant files)
+
+2008-02-29 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemonutils.[ch]:
+ Rename gvfs_file_info_populate_names() to
+ gvfs_file_info_populate_names_as_local() and
+ add docs explaining when to use this function
+ and when not to.
+
+2008-02-29 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemonutils.c:
+ (gvfs_file_info_populate_content_types):
+ Use g_content_type_get_icon() for the icon mapping.
+ Use folder, not folder-remote for icon. I don't
+ think we should use folder-remote for things like
+ shares, not normal folders.
+
+2008-02-29 Cosimo Cecchi <cosimoc@gnome.org>
+
+ * daemon/gvfsbackendcomputer.c: (recompute_files),
+ (mount_volume_from_drive), (report_no_media_error),
+ (poll_for_media_cb), (try_mount_mountable):
+ Implement media polling for Computer backend, handling the case when
+ no media is in the drive. Also adds a new string. (#514135)
+
+2008-02-29 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * daemon/gvfsbackendnetwork.c (g_vfs_network_daemon_init):
+
+ Added another translator comment.
+
+2008-02-29 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * daemon/gvfsbackendftp.c (do_mount):
+
+ Added translator comment.
+
+2008-02-29 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * daemon/gvfsbackendftp.c (g_vfs_backend_ftp_pop_connection):
+
+ Reuse existing string to reduce the impact of the string
+ freeze breaks.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ actually translate the display name
+
+2008-02-28 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/gvfsbackendnetwork.c: (g_vfs_network_daemon_init):
+ * daemon/gvfsbackendnetwork.h:
+ Set the default name for the network backend to prevent
+ possible confusion about "NETWORK Filesystem Service".
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ really check for errors correctly. I need to go to bed.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ check for errors correctly
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ reviewed by: A. Walton <awalton@svn.gnome.org>
+
+ * daemon/daemon-main-generic.c: (main):
+ * daemon/daemon-main.c: (daemon_setup):
+ * daemon/daemon-main.h:
+ * daemon/gvfsbackendcdda.c: (g_vfs_cdda_daemon_init):
+ * daemon/gvfsbackendcdda.h:
+ * daemon/gvfsbackendsmb.c: (g_vfs_smb_daemon_init):
+ * daemon/gvfsbackendsmb.h:
+ * daemon/gvfsbackendsmbbrowse.c: (g_vfs_smb_browse_daemon_init):
+ * daemon/gvfsbackendsmbbrowse.h:
+ provide default application names for the daemons. This is necessary
+ to avoid gnome-keyring from saying "Application" wants access to the
+ keyring, which could sound very evil for a casual user.
+ Adds some more strings for the poor translators, too!
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount), (try_mount):
+ rewrite login code to use the keyring if available. Also fix mount
+ specs to be unique and display names to list the user while at it.
+
+2008-02-28 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/Makefile.am:
+ Really disable FTP if we don't HAVE_HTTP.
+
+2008-02-28 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/gvfsbackendnetwork.c: (recompute_files):
+ Fixup DNS-SD exposed links to actually link to the service provided.
+
+2008-02-28 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c (g_vfs_backend_dav_init):
+ Mark the dav backend as user visible.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_create),
+ (ftp_connection_login), (ftp_connection_use), (ftp_connection_new):
+ split out login code, so we can try multiple auths when some fail.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsdaemonutils.c: (gvfs_file_info_populate_default),
+ (gvfs_file_info_populate_names),
+ (gvfs_file_info_populate_content_types):
+ * daemon/gvfsdaemonutils.h:
+ add functions that are supposed to set default values on a remote file
+ info structure, so we don't duplicate the code across multiple
+ backends.
+
+ * daemon/gvfsbackendftp.c: (ftp_error_set_from_response),
+ (ftp_connection_new), (file_info_get_flags), (file_info_query):
+ use it.
+
+2008-02-28 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvolumemonitor.c:
+ (mount_added):
+ (mount_removed):
+ Emit signals outside of the lock to avoid
+ deadlocks (#519250)
+
+2008-02-28 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp-fl-parser.c (fl_parser_start_node_cb):
+ Fix the content-type of directories (inode/directory, not
+ x-directory/normal as in gnome-vfs)
+ Set file icons from the content-type
+
+ * daemon/gvfsbackendobexftp.c (_change_directory):
+ Add a FIXME, trying to change to a non-existant directory
+ errors out with "permission denied", which isn't the case
+
+ (_query_file_info_helper): set the right content-type and icon
+ for the root folder
+
+ (is_connected), (do_mount): Wait until we're connected to exit from
+ do_mount()
+
+ (do_open_for_read): Fix a crash when opening an inexistant file for
+ read
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_error_set_from_response),
+ (file_info_query), (do_query_info):
+ Set sane error messages for ftp error codes.
+ Also remove some excessive debug messages.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (do_mount):
+ fix typo (thanks Andre)
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsbackendftp.c: (ftp_connection_sendv),
+ (ftp_connection_send), (do_start_write), (do_create), (do_append),
+ (do_replace), (g_vfs_backend_ftp_class_init):
+ implement append
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ gcc warning fixes to be able to compile with -Werror:
+ * daemon/gvfsbackendburn.c:
+ mark virtual_node_ref as unused, because it is
+ * test/benchmark-common.c: (benchmark_timeout):
+ signal handlers take an int argument.
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * configure.ac:
+ list FTP in configuration summary, too
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendftp.h:
+ drop my current FTP code and continue development in here. Should make
+ testing easier for adventurous people.
+
+2008-02-28 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp.c (do_query_info): Add
+ missing mutex unlock, duh!
+
+2008-02-28 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsjobenumerate.c: (g_vfs_job_enumerate_add_infos):
+ * daemon/gvfsjobenumerate.h:
+ constify list argument, so ownership is apparent.
+
+2008-02-28 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendobexftp-fl-parser.c (fl_parser_start_node_cb):
+ Set the content-type on files by having a good guess if we didn't
+ get a mime-type from the folder listings
+
+2008-02-27 Benjamin Otte <otte@gnome.org>
+
+ * programs/gvfs-mount.c: (prompt_for):
+ don't mess up my terminal when entering passwords
+
+2008-02-27 Bastien Nocera <hadess@hadess.net>
+
+ * client/test-uri-utils.c: add test for obex URIs
+ * configure.ac: Require expat for the obexftp backend
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendobexftp-cap-parser.c:
+ * daemon/gvfsbackendobexftp-cap-parser.h:
+ * daemon/gvfsbackendobexftp-fl-parser.c:
+ * daemon/gvfsbackendobexftp-fl-parser.h:
+ Added ObexFTP folder listing and capability parser from
+ gnome-vfs-obexftp, ported to gio
+
+ * daemon/gvfsbackendobexftp.c:
+ * daemon/gvfsbackendobexftp.h:
+ * daemon/obexftp-marshal.list:
+ * daemon/obexftp.mount.in: Add read-only ObexFTP backend
+
+ (Closes: #509621)
+
+2008-02-27 Luca Ferretti <elle.uca@libero.it>
+
+ * daemon/gvfsbackendcdda.c: (do_query_info):
+ Make "file don't exist" message conform to other backends;
+ no, it isn't a string freeze break, the message yet exists
+ elsewhere.
+
+2008-02-27 Benjamin Otte <otte@gnome.org>
+
+ * common/gmountsource.c: (g_mount_source_ask_question_finish):
+ Set out parameters for questions, too.
+
+2008-02-27 Benjamin Otte <otte@gnome.org>
+
+ * common/gmountsource.c: (g_mount_source_ask_password_finish):
+ Set out parameters even in error case.
+
+2008-02-26 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c: (do_delete):
+ Correct error domain in case delete failed.
+
+2008-02-26 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Redo authentication and implement keyring support. Based
+ on a patch by Carlos Garcia Campos.
+
+2008-02-26 Alexander Larsson <alexl@redhat.com>
+
+ * programs/gvfs-bash-completion.sh:
+ * programs/gvfs-ls.c:
+ Better completion
+
+2008-02-26 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsjobmount.c (run):
+ No need to ref backend specifically now, as
+ the core refs the job and the job refs the
+ backend. Revert that change.
+
+2008-02-26 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsjob.c:
+ (g_vfs_job_run):
+ (g_vfs_job_try):
+ Ref job while calling out.
+
+ * daemon/gvfsjobmount.c:
+ Own ref to backend while job is alive.
+
+2008-02-26 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfsbackendsmb.c: (auth_callback):
+ Fix parameters order in keyring lookup call.
+
+2008-02-26 Yanko Kaneti <yaneti@declera.com>
+
+ * configure.ac: explicitly depend on libxml-2.0
+ for building the dav backend.
+
+2008-02-26 Benjamin Otte <otte@gnome.org>
+
+ * common/gmountsource.c: (ask_password_reply),
+ (g_mount_source_ask_password_async), (ask_question_reply),
+ (g_mount_source_ask_question_async):
+ make errors say "Internal Error" instead of failing
+
+2008-02-26 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsjobmount.c: (run), (try):
+ use ref/unref pair to stop backend from going away when the mount
+ fails
+
+2008-02-26 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsjobmount.c: (mount_failed):
+ no g_warning for failed monts, please
+
+2008-02-26 Benjamin Otte <otte@gnome.org>
+
+ * daemon/gvfsjob.c: (g_vfs_job_failed_from_error):
+ * daemon/gvfsjob.h:
+ make the error argument const
+
+2008-02-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvolumemonitor.c:
+ Use standard lock instead of recursive lock.
+
+2008-02-25 David Zeuthen <davidz@redhat.com>
+
+ * configure.ac: fix typo in AC_ARG_ENABLE for gphoto2
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.c:
+ * daemon/dbus-gmain.c:
+ Only use dbus_watch_get_unix_fd for
+ dbus >= 1.1.1
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.8 ===
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * programs/Makefile.am (EXTRA_DIST):
+ Add gvfs-bash-completion.sh
+
+ * NEWS:
+ Update for release
+
+2008-02-25 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ Update to gvfskeyring api changes
+
+ * daemon/gvfskeyring.c:
+ * daemon/gvfskeyring.h:
+ Add object, authtype and port parameters for both save and
+ lookup.
+
+2008-02-25 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Initial take on implementing delete.
+
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Add http_error_code_from_status helper function.
+
+2008-02-25 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Also check if the URL is a directory by doing a PROPFIND in
+ addition to the OPTIONS. That will also force authentication
+ since some servers (e.g. Zope) allow OPTIONS without doing
+ authentication.
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * client/sftpuri.c:
+ Make sure both no-port and port 22 refer to the same mount.
+
+ * daemon/gvfsbackendsftp.c:
+ Support ports. (#518504)
+
+2008-02-25 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Keep the SoupMessage around for as long as Multistatus is
+ valid.
+
+2008-02-25 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Add a SoupSessionAsync to be used for SoupInputStream doesn't
+ yet work with SoupSessionSync. Also make sure we share
+ authentication.
+
+2008-02-25 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ - Port the mount operation to use the sync i/op.
+ - Keep the auth information around so we can use them again in
+ the case that a subpath requires different authentication. This
+ is needed since libsoup will forgot all auth after a 401.
+ - Ignore trailing slashes in ms_response_is_target ().
+ - Add an initial version of make_directory ().
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Add message_new_from_filename_full which will add a trailing "/"
+ if is_dir is true. (Saves uneccesary redirects in some cases)
+
+ Various bits and pieces came from Yann Rouillard.
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ Support gnome-keyring (#511517)
+ Patch from Carlos Garcia Campos
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c (recompute_files):
+ Fix spelling inconsistency "Network" vs "network" (#518487)
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c (get_mountspec_from_uri):
+ g_uri_get_scheme -> g_uri_parse_scheme
+
+2008-02-25 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * hal/ghalvolume.c (do_update_from_hal_for_camera): Add
+ two translator comments.
+
+2008-02-24 David Zeuthen <davidz@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonvolumemonitor.c:
+ * client/gdaemonvolumemonitor.h: Prefer to return a GDaemonMount
+ from an existing GDaemonVolumeMonitor rather than rolling our own
+ for GDaemonFile's g_file_find_enclosing_mount()
+ implementation. This is to ensure that g_mount_get_volume() will
+ work properly with mounts that are adopted by GVolume objects from
+ other volume monitors.
+
+ * configure.ac: Check for libgphoto2
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendcdda.c: Use HAL to detect when the disc is
+ removed and then forcibly unmount the mount. Report size of
+ disc. Hint the file manager to preview files.
+
+ * hal/ghaldrive.c:
+ * hal/ghalmount.c:
+ * hal/ghalvolume.c:
+ * hal/ghalvolumemonitor.c:
+ * hal/ghalvolumemonitor.h:
+ * hal/hal-pool.c: Ensure that audio and blank CD's are
+ displayed (#514139). Read info.desktop.[icon|name] properties
+ from hal and use these if found. Use proper icon for audio players
+ and make the gphoto2 detection support it as well. Also check for
+ subsystem when filtering on hal capabilities. Also revert the
+ commit to ignore NFS mounts as gio will now only report an user
+ visible mount if it's in /media or $HOME. Make LUKS encrypted
+ volumes work.
+
+ * daemon/Makefile.am:
+ * daemon/gphoto2.mount.in:
+ * daemon/gvfsbackendgphoto2.c:
+ Land the gphoto2 backend.
+
+ * programs/Makefile.am:
+ * programs/gvfs-ls.c: Make the --hidden option work. Default
+ to short listing and add a --long option. Implement new options
+ --show-completions and --show-mounts that can be used for
+ shell completions.
+ * programs/gvfs-tree.c: New program
+ * programs/gvfs-bash-completion.sh: Bash completion for gvfs;
+ uses the new --show-completions and --show-mounts options in
+ gvfs-ls.
+
+2008-02-25 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c:
+ Add monitoring of inlined locations. (#509600)
+ Patch from A. Walton
+
+2008-02-22 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/gvfsbackendnetwork.c: (recompute_files):
+ Make network:// really add extra domain links.
+
+2008-02-22 A. Walton <awalton@svn.gnome.org>
+
+ * daemon/gvfsbackendnetwork.c: (recompute_files):
+ Fix typo so we generate correct dns-sd links.
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c:
+ (g_vfs_backend_network_init):
+ Fix up dns-sd method name and gconf directory.
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/dns-sd.mount.in:
+ Correct type and exec name
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.c:
+ Unlock lock if returning early.
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ * daemon/Makefile.am:
+ * daemon/dns-sd.mount.in:
+ * daemon/gvfsbackenddnssd.[ch]:
+ Landed initial version of dns-sd backend.
+
+2007-02-22 Christian Neumair <cneumair@gnome.org>
+
+ * gconf/gconf-module.c: (g_io_module_load):
+ * gconf/Makefile.am:
+ * hal/hal-module.c: (g_io_module_load):
+ * hal/Makefile.am:
+ * client/gdaemonvfs.c: (g_daemon_vfs_init):
+ * client/Makefile.am:
+ Bind to GVFS text domain. Fixes #517892.
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c:
+ Fix up network_file_equal.
+
+2008-02-22 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendnetwork.c:
+ Update the network backend to use inline files and
+ remove the default workgroup link. Also add dns-sd
+ support (not used yet). (#509600)
+ Patch from A. Walton
+
+2008-02-22 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfsbackendsftp.c: (handle_login), (do_mount):
+ Ask for the username in the sftp login when it's not
+ provided. (#511509)
+
+2008-02-21 Christian Persch <chpe@gnome.org>
+
+ * configure.ac: Update hal req to 0.5.10. Bug #515779.
+
+2008-02-21 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfsbackendsftp.c: (handle_login):
+ Fix memory leak.
+
+2008-02-21 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * daemon/gvfsbackendsftp.c: (handle_login):
+ Fix password save flags initialization.
+
+2008-02-21 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac (DISTCHECK_CONFIGURE_FLAGS):
+ Require latest glib for the contains_file
+ change.
+
+2008-02-21 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ (g_daemon_file_prefix_matches):
+ (g_daemon_file_file_iface_init):
+ Update for the contains_file rename in gio.
+
+2008-02-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ If gconf availible, initialize default workgroup
+ from gconf.
+ Handle X-GNOME-DEFAULT-WORKGROUP special case
+ to list the current workgroup
+
+2008-02-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/daemon-main.c (send_spawned):
+ Fix "_" spew.
+
+2008-02-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Fix spelling in string
+
+2008-02-20 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountsource.[ch]:
+ Add ask_question support
+
+ * daemon/gvfsbackendsftp.c:
+ Handle host identity changed messages (#517460)
+
+ Patch from Carlos Garcia Campos
+
+2008-02-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendnetwork.[ch]:
+ * daemon/network.mount.in:
+ Initial network backend work (#509600)
+
+2008-02-19 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Authentication fixups (#511517)
+ Patch from Carlos Garcia Campos
+
+2008-02-19 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendtrash.c:
+ * gconf/gapplookupgconf.c:
+ * test/benchmark-common.c:
+ Some more cleanup.
+
+2008-02-19 Alexander Larsson <alexl@redhat.com>
+
+ * lots of *.c files:
+ Code cleanup from Kjartan:
+ Removes unused code/variables.
+ Uses right printf types
+ Uses non-deprecated dbus calls.
+ Removes spurious ; and ,
+ deleted extra checks for NULL for g_free
+
+2008-02-18 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalmount.c:
+ Cleanups of case insensitive search. (#154549)
+ patch from John Millikin.
+
+2008-02-18 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsjobenumerate.c (g_vfs_job_enumerate_add_info):
+ Ensure we're using "/" as separator for uris.
+ This only affects win32, which probably doesn't work atm, but
+ still its nice to be explicit.
+
+2008-02-18 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Detect gnome-keyring
+
+ * common/gmountsource.[ch]:
+ Add password out to ask_password
+
+ * daemon/Makefile.am:
+ * daemon/gvfskeyring.[ch]:
+ Helper code for keyring support
+
+ * daemon/gvfsbackendsftp.c:
+ Add keyring support
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendsmb.c:
+ Update to api changes
+
+ This is the initial work on keyring support (#511517)
+ Patch from Carlos Garcia Campos
+
+2008-02-16 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/soup-input-stream.c:
+ * daemon/soup-output-stream.c:
+ Use SoupSessionSync instead of SoupSessionAsync and
+ convert SoupStreams and authentication logic.
+
+2008-02-15 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsjobenumerate.c:
+ Fix a little crasher (NULL terminate g_build_filename) that
+ was introduced by the optional uri addition change to enumerate.
+
+2008-02-15 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Completly redo Multistatus parsing.
+
+2008-02-15 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ Pass uri in query_info_async too.
+
+2008-02-15 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ Pass an optional uri to query_info and enumerate
+
+ * daemon/gvfsbackend.[ch]:
+ Add automatic info filling, implement thumbnail
+ checking if uri passed in.
+
+ * daemon/gvfsjobenumerate.[ch]:
+ * daemon/gvfsjobqueryinfo.[ch]:
+ Get optional uri argument.
+ Call automatic backend info filling.
+
+2008-02-15 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackendhttp.c: (g_vfs_backend_uri_for_filename):
+ Escape the filename.
+
+2008-02-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c:
+ If lookup returns NULL it already set the error.
+ Handle this in all callers.
+
+2008-02-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ Disable install of ftp.mount for now
+
+2008-02-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfschannel.c:
+ Fix case where current_job has died (NULL) but
+ the current_job_seq_nr was left and matched
+ a sent cancel op. (#515959)
+
+2008-02-13 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsmb.c (do_read):
+ Limit smb reads to 65535 bytes to avoid issues on
+ large reads.
+
+2008-02-13 Ryan Lortie <desrt@desrt.ca>
+
+ * daemon/gvfsbackendtrash.c:
+ Keep track of the number of top level items in the trash.
+ Expose this value via the trash::item-count attribute.
+
+2008-02-13 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalmount.c:
+ Don't show nfs mounts (#516036)
+
+2008-02-12 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c (g_hal_volume_monitor_finalize):
+ Don't double free list optical disc list.
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.7 ===
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Set the correct copy name.
+ Set description.
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsmb.c:
+ (do_set_display_name):
+ Fix typo: get_dirname, not get_basename.
+ Fixes renames on smb (#514126)
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Set new path in set_display name.
+
+ * daemon/gvfsjobsetdisplayname.c:
+ Assert that new_path is set
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * common/gsysutils.c:
+ * common/gvfsdaemonprotocol.c:
+ * daemon/gvfsbackendburn.c:
+ * daemon/gvfsbackendcdda.c:
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtest.c:
+ * daemon/gvfsdaemonutils.c:
+ * daemon/gvfsjob.c:
+ * daemon/mount.c:
+ * daemon/pty_open.c:
+ Save errno befor making other calls.
+ Be safe when calling g_set_error()
+ Patch from Christian Persch (#514822)
+
+2008-02-11 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * daemon/gvfsbackendcomputer.c:
+ * hal/ghalvolume.c:
+ * programs/gvfs-mount.c:
+ Update for the new mount flag argument.
+
+ * hal/ghaldrive.c:
+ * programs/gvfs-open.c:
+ Fix warnings
+
+2008-02-10 Luca Ferretti <elle.uca@libero.it>
+
+ * daemon/gvfsbackendburn.c: (g_vfs_backend_burn_init),
+ (file_info_from_node):
+ Rename burn:// with old "CD/DVD Creator" name.
+
+ * daemon/gvfsbackendtrash.c: (g_vfs_backend_trash_init),
+ (do_query_info):
+ Rename trash:// with old "Trash" name.
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolume.c:
+ Implement g_volume_should_automount.
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c:
+ Add "filesystem" to computer:
+
+ * hal/ghalmount.c:
+ Remove spew
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalmount.c:
+ Try to find cdrom icons from autorun.inf.
+ Based on patch from John Millikin
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.c:
+ Fix up indentation
+ Don't unref file from g_file_icon_get_file().
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Always set CAN_TRASH to false
+
+2008-02-08 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c (unescape_pathname):
+ Handle unescaping __ correctly (#514040)
+
+2008-02-06 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ Ensure name is set in query_info (#511601)
+ Clean up setting display name of /
+
+2008-02-05 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvolumemonitor.c (mount_removed):
+ Don't spew warnings when hidden mounts are unmounted.
+
+2008-02-05 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ (do_query_info):
+ Correctly set the name for toplevel items.
+
+2008-02-04 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsjobmakesymlink.c:
+ Wrong symlink target passed to backend
+
+2008-02-04 Alexander Larsson <alexl@redhat.com>
+
+ * README:
+ Add some info in README
+
+2008-02-04 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Make name of sftp root be "/ on <host>" (#511515)
+
+2008-02-04 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsdaemonutils.c:
+ * hal/ghalvolume.c:
+ Cleanup i18n strings (#510192)
+
+2008-02-04 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.h:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * daemon/gvfsreadchannel.c:
+ * daemon/gvfswritechannel.c:
+ Remove SEEK_CUR from channel protocol. This
+ doesn't work with readahead, and can be converted
+ to a SEEK_SET since we know the file position on
+ the client side.
+
+2008-02-04 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ Init seq_nr to 1 so that seq_nr 0 is special
+ (used for e.g. readahead ops)
+
+ * daemon/gvfschannel.[ch]:
+ * daemon/gvfsreadchannel.c:
+ Implement readahead.
+
+2008-02-03 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ Move write logic (replace, create) to the dav backend.
+
+2008-02-01 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsreadchannel.c:
+ Request larger buffers than the client requested
+ so for better network efficiency. (#512472)
+
+2008-02-01 Alexander Larsson <alexl@redhat.com>
+
+ * programs/gvfs-open.c:
+ Pass on uris unmodified to avoid roundtripping
+ through GFile which can be destructive.
+
+2008-01-31 Alexander Larsson <alexl@redhat.com>
+
+ Implement uri navigation for http uris (#509341)
+
+ * client/gvfsurimapper.[ch]:
+ Add get_mount_info_for_path method for mount types
+ like ssh that change MountInfo as the path changes.
+
+ * client/httpuri.c:
+ Implement get_mount_info_for_path.
+ For http, set the path from the uri.
+ The will be removed on i/o by the corresponding
+ path being in the mount_prefix.
+
+ * daemon/gvfsbackendhttp.c:
+ Set mount_prefix to path from uri.
+ Remove unused code in message_new_from_filename
+
+ * client/gdaemonfile.c:
+ * client/gdaemonvfs.[ch]:
+ Use the new uri mapper function to change GMountInfo
+ as the path changes.
+
+2008-01-31 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountspec.[ch]:
+ Add shared path canonicalization:
+ g_mount_spec_canonicalize_path()
+
+2008-01-31 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/soup-input-stream.c:
+ Handle errors in send_finish.
+
+2008-01-30 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendlocaltest.c:
+ Use read/write operations instead of do_copy ()
+
+2008-01-30 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c:
+ Set read and execute privs for all directories.
+ Fix up type when reading can-read etc attributes.
+ Don't use uid/gid in the fuse mount. The
+ uid/gid doesn't make sense locally anyway.
+
+2008-01-30 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackend.c:
+ (g_vfs_backend_register_mount):
+ Correctly detect unset stable name
+
+2008-01-29 Tomas Bzatek <tbzatek@redhat.com>
+
+ * daemon/gvfsbackendlocaltest.c:
+ Fixed error handling in do_enumerate ()
+ More cleanup
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile.am:
+ * configure.ac:
+ * gconf/Makefile.am: Added.
+ * gconf/gapplookupgconf.[ch]: Added.
+ * gconf/gconf-module.c: Added.
+ Add gconf based implementation of
+ g_app_info_get_default_for_uri_scheme ()
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c (g_hal_volume_monitor_class_init):
+ Remove setting prio/name
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Require glib 2.15.5 for g_file_query_default_handler ().
+
+ * programs/Makefile.am:
+ * programs/gvfs-open.c:
+ Added gvfs-open app
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.6 ===
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+ * daemon/Makefile.am:
+ Always dist all .mount.in files
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.5 ===
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/daemon-main.c:
+ * daemon/main.c:
+ Include locate.h for setlocale
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * hal/hal-device.c:
+ Use gi18n-lib.h, not gi18n.h in client side code.
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c (g_daemon_file_move):
+ Fix typo G_DAEMON_FILE -> G_IS_DAEMON_FILE
+
+ * configure.ac:
+ Require glib >= 2.15.4
+
+ * client/gdaemonvfs.c:
+ * client/gdaemonvolumemonitor.c:
+ * hal/ghalvolumemonitor.c:
+ Register with the new extension points API.
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendlocaltest.c:
+ * programs/gvfs-cat.c:
+ C89 fixes from Jens Granseuer (#511838)
+
+2008-01-28 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ * daemon/daemon-main.c:
+ * daemon/main.c:
+ Enable translations for daemons and some l10n
+ fixes. Patch from Luca Ferretti.
+
+2008-01-24 Matthias Clasen <mclasen@redhat.com>
+
+ * daemon/gvfsbackendsmbbrowse.c
+ (get_file_info_from_entry): Replace : by :: in
+ smb::comment, too.
+
+2008-01-24 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Update intltool req for po/LINGUAS
+
+2008-01-24 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ Remove debug spew.
+
+ * hal/ghaldrive.c:
+ * hal/ghalvolume.c:
+ Implement identifier getters
+
+ * programs/gvfs-mount.c:
+ Show identifiers
+
+2008-01-24 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemon.c:
+ Indentation fix
+
+ * hal/ghaldrive.[ch]:
+ * hal/hal-device.c:
+ * hal/ghalvolume.c:
+ * hal/ghalmount.c:
+ Clean up coding style
+
+ * hal/ghalvolumemonitor.[ch]:
+ Clean up coding style
+ Don't show drives if we're ignoring all their
+ volumes (and there are volumes)
+
+ * hal/hal-pool.c:
+ Clean up coding style
+ Actually look at cap_only.
+ Free private dbus_connection on error
+
+2008-01-24 Bastien Nocera <hadess@hadess.net>
+
+ * programs/Makefile.am:
+ * programs/gvfs-mkdir.c: (main): Add a test mkdir program
+
+2008-01-23 Bastien Nocera <hadess@hadess.net>
+
+ * client/test-uri-utils.c: (main):
+ * client/Makefile.am: Add test program for the
+ functions in gvfsuriutils.c
+
+ * client/gvfsuriutils.c: (g_vfs_decode_uri):
+ Fix parsing of IPv6 URIs where the host is in brackets
+
+2008-01-23 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ (add_extra_trash_info):
+ Use -, not _ in attribute names
+
+2008-01-23 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ (add_extra_trash_info):
+ Use :: to delimit namespace for trash attributes
+
+2008-01-22 Gil Forcada <gforcada@gnome.org>
+
+ * configure.ac: Added ca to ALL_LINUGAS.
+
+2008-01-22 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Ensure we return a IS_DIRECTORY error when
+ we open a file for reading (#511225)
+ The same needs to happen for writes.
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.4 ===
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/sftpuri.c:
+ * common/gmounttracker.c:
+ * daemon/gvfsmonitor.c:
+ * daemon/gvfsbackend.c:
+ Fix warnings
+
+ * daemon/gvfsbackendburn.c:
+ * daemon/gvfsbackendlocaltest.c:
+ * daemon/gvfsbackendtrash.c:
+ Update to latest gio API (removal of
+ duplicate GSeekable calls).
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.3 ===
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+ * daemon/Makefile.am:
+ * daemon/main.c:
+ Autospawn fuse on daemon start.
+
+ * daemon/mount.c:
+ (read_mountable_config):
+ Remove debug spew
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c:
+ Fix error with the names of the root items the
+ fuse mount.
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/mount.c:
+ Reload the list of mountables on SIGUSR1
+
+2008-01-21 Christian Kellner <gicmo@gnome.org>
+
+
+ * daemon/gvfsbackenddav.c:
+ Small cleanups.
+
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Implement query_info for plain http.
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * client/gdaemonvfs.c:
+ * client/sftpuri.c: Added.
+ Added sftp uri mapper that aliases ssh: to sftp: (#509860)
+
+ * client/smburi.c:
+ (smb_from_uri):
+ Fix leak.
+
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.c:
+ Do the initial mount tracker call sync so that
+ the volume monitor is populated with the current
+ status after construction. This is more in-line
+ with what apps expect.
+
+2008-01-18 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountspec.c:
+ (g_mount_spec_new_from_data):
+ Ensure that mount_prefix is never NULL. It
+ should be "/" in that case.
+
+2008-01-18 Luca Ferretti <elle.uca@libero.it>
+
+ * programs/Makefile.am:
+ * programs/gvfs-cat.c: (cat), (main):
+ Add i18n/l10n to gvfs-cat, plus indentation. For details see
+ http://mail.gnome.org/archives/gnome-vfs-list/2008-January/msg00020.html
+
+2008-01-18 David Zeuthen <davidz@redhat.com>
+
+ The volume monitor bits of gphoto2 support. The actual backend
+ will follow later. Right now the code is only enabled on Linux,
+ need trivial changes to work on other operating systems.
+
+ * hal/ghalvolume.c: (do_update_from_hal_for_camera),
+ (update_from_hal), (g_hal_volume_new):
+ * hal/ghalvolumemonitor.c: (get_hal_pool),
+ (g_hal_volume_monitor_finalize), (get_volumes),
+ (mountpoints_changed), (mounts_changed),
+ (g_hal_volume_monitor_force_update), (hal_changed),
+ (g_hal_volume_monitor_constructor), (find_camera_volume_by_udi),
+ (update_cameras):
+ * hal/ghalvolumemonitor.h:
+ * hal/hal-pool.c: (hal_pool_finalize), (has_cap_only),
+ (hal_pool_add_device_by_udi),
+ (hal_pool_add_device_by_udi_and_properties), (hal_pool_new):
+ * hal/hal-pool.h:
+
+2008-01-17 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ Disconnect signal handler, since the data struct we pass
+ into the signal handler will be invalid after the mount
+ is finished.
+
+2008-01-17 Christian Kellner <gicmo@gnome.org>
+
+ * common/gmountsource.c:
+ * common/gmountsource.h:
+ Make g_mount_source_ask_password_async () public and add
+ g_mount_source_ask_password_finish ().
+
+ * daemon/gvfsbackenddav.c:
+ Use g_mount_source_ask_password_async instead of the sync
+ version so we don't hang during auth. Few cleanups.
+
+ * programs/gvfs-mount.c:
+ Don't echo the password, if possible.
+
+2008-01-17 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolume.c:
+ * hal/ghalvolumemonitor.c:
+ Initial work on LUKS, from david.
+
+2008-01-17 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.h:
+ * client/gdaemonfile.c:
+ Add upload operation (requires latest glib)
+
+ * daemon/gvfsbackend.[ch]:
+ * daemon/gvfsjobupload.[ch]: Added.
+ Implement upload in daemon
+
+ * daemon/Makefile.am:
+ * daemon/burn.mount.in: Added.
+ * daemon/gvfsbackendburn.[ch]: Added.
+ Added initial burn:/// implementation.
+ Not fully implemented, but read works.
+
+ * daemon/gvfsbackendcomputer.c:
+ Ensure we set right mimetype for dirs
+
+2008-01-16 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ A few cleanups.
+
+2008-01-16 Christian Kellner <gicmo@gnome.org>
+
+ * daemon/gvfsbackenddav.c:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ * daemon/soup-input-stream.c:
+ * daemon/soup-output-stream.c:
+ Port to libsoup-2.4.
+
+ * configure.ac:
+ * daemon/Makefile.am:
+ Make building of http optional (and depend on wether
+ libsoup is found or not)
+ Patch from Dan Winship.
+
+2008-01-16 Frederic Crozat <fcrozat@mandriva.com>
+
+ * Makefile.am: Only build hal module when hal support is
+ enabled (#509693).
+
+2008-01-15 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * daemon/daemon-main.c:
+ * daemon/gvfsbackendcdda.c:
+ * daemon/gvfsbackendcomputer.c:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendlocaltest.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsjobsetattribute.c:
+ * hal/ghaldrive.c:
+ Clean up strings and add translator comments
+
+2008-01-15 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c:
+ (recompute_files):
+ Fix crash (#508236)
+ Patch from Joe Marcus Clarke
+
+2008-01-15 David Zeuthen <davidz@redhat.com>
+
+ * hal/ghaldrive.c: (_eject_unmount_mounts_cb),
+ (_eject_unmount_mounts), (g_hal_drive_eject):
+ * hal/ghalvolume.c: (g_hal_volume_new), (g_hal_volume_can_mount),
+ (g_hal_volume_has_device_path), (g_hal_volume_mount),
+ (g_hal_volume_eject):
+ * hal/ghalvolume.h:
+ * hal/ghalvolumemonitor.c:
+ (g_hal_volume_monitor_lookup_volume_for_device_path),
+ (update_volumes), (update_mounts), (update_discs):
+ Fix debug spew and use try device path before mount path to tie
+ volume and mount objects together. Also fix some issues with
+ mounting and unmounting.
+
+2008-01-15 Daniel Nylander <po@danielnylander.se>
+
+ * configure.ac: Added sv to ALL_LINGUAS.
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.2 ===
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac (DISTCHECK_CONFIGURE_FLAGS):
+ Require glib 2.15.2
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * daemon/gvfsbackendlocaltest.c:
+ * daemon/gvfsbackendtrash.c:
+ * programs/gvfs-monitor-dir.c:
+ * programs/gvfs-monitor-file.c:
+ Update to new gio API
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ (match_prefix):
+ Handle root correctly in g_file_get_relative_path (#508719)
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemon.c:
+ Don't translate g_warning strings
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/httpuri.c:
+ (http_from_uri):
+ Only set "ssl" key in dav case.
+
+2008-01-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/httpuri.c:
+ (http_to_uri_scheme):
+ Fix some crashes
+
+2008-01-13 Dan Winship <danw@gnome.org>
+
+ * client/httpuri.c (http_from_uri): fix
+
+ * daemon/soup-output-stream.c: Initial SoupOutputStream; still
+ works like gnome-vfs http did, by storing all the writes in memory
+ until close.
+
+ * daemon/gvfsbackendhttp.c (try_create, try_replace): Implement.
+ For now we need to do HEAD-then-PUT, but we may later be able to
+ do a single PUT with "Expect: 100-continue".
+ (try_write, try_close_write): Implement.
+
+2008-01-13 Christian Kellner <gicmo@gnome.org>
+
+ * client/httpuri.c:
+ Also handle dav uris in the http mapper.
+
+ * daemon/dav.mount.in:
+ * daemon/Makefile.am:
+ Add the new dav backend.
+
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Implement a utility function so dav and http
+ backend can share uri from filename creation.
+
+ * daemon/gvfsbackenddav.c:
+ First attempt to write the dav backend as a subclass of http.
+ Mount, QueryInfo, Enumerate should work and Read is provided
+ by the base class.
+
+2008-01-12 Leonid Kanter <leon@asplinux.ru>
+
+ * configure.ac: Added "ru" (Russian) to ALL_LINGUAS.
+
+2008-01-12 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ Set the http daemon dbus busname so that multiple mounts
+ work in the same process.
+
+2008-01-11 Dan Winship <danw@gnome.org>
+
+ * daemon/soup-input-stream.c: implement GSeekable (a bit hackishly
+ due to a bug in libsoup 2.2.x)
+
+ * daemon/gvfsbackendhttp.c (try_seek_on_read): implement
+
+2008-01-11 Dan Winship <danw@gnome.org>
+
+ * daemon/gvfsbackendhttp.c (g_vfs_backend_http_finalize): cleanup
+ (g_vfs_backend_http_init): move session creation here. Don't
+ explicitly set ASYNC_CONTEXT to g_main_context_default() because
+ that trips up SoupInputStream.
+ (uri_for_filename): create a SoupUri corresponding to a filename.
+ In particular, "/" corresponds to mount_base, not the result of
+ combining mount_base with "/".
+ (try_open_for_read): use uri_for_filename, free the result.
+
+2008-01-11 Dan Winship <danw@gnome.org>
+
+ * daemon/soup-input-stream.c (soup_input_stream_send)
+ (wrapper_callback, soup_input_stream_send_async): Fix for changes
+ to g_input_stream_set_pending() since I wrote this.
+
+ * client/gdaemonfile.c (g_daemon_file_hash): x86_64 fix.
+
+2008-01-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendhttp.c:
+ Make http mount not user visible.
+ Set backend mount spec in try_mount.
+
+2008-01-11 Christian Kellner <gicmo@gnome.org>
+
+ * client/gdaemonvfs.c:
+ Fix the double use of a counter variable inside nested loops.
+
+ * client/Makefile.am:
+ * client/httpuri.c:
+ UriMapper added, which is needed for plain http method.
+
+ * configure.ac:
+ Check for libsoup version >= 2.2.104
+
+ * daemon/gvfsbackendhttp.c:
+ Initial implementation of plain http methods.
+
+ * daemon/Makefile.am:
+ * daemon/http.mount.in:
+ Added.
+
+ * daemon/soup-input-stream.c:
+ * daemon/soup-input-stream.h:
+ Import of Dan Winship's libsoup based streaming classes.
+
+2008-01-11 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * configure.ac: Added "eu" (Basque) to ALL_LINGUAS.
+
+2008-01-11 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendcomputer.c:
+ Set can't write info on the root.
+
+2008-01-11 Alexander Larsson <alexl@redhat.com>
+
+ * programs/gvfs-mount.c (list_volumes):
+ Fix crash if no mount in volume.
+
+2008-01-11 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * common/gvfsdaemonprotocol.h:
+ Implement unmount_mountable and eject_mountable
+ on client side.
+
+ * common/gmountoperationdbus.c:
+ Fix warnings
+
+ * daemon/gvfsbackend.[ch]:
+ * daemon/gvfsjobunmountmountable.[ch]:
+ Add unmount_mountable and eject_mountable in daemon.
+
+ * daemon/gvfsbackendcomputer.c:
+ Implement unmount_mountable and eject_mountable
+
+ * daemon/gvfsbackendlocaltest.c:
+ Update to latest API
+
+ * daemon/gvfsbackendsftp.c:
+ Fix indentation
+
+ * daemon/gvfsjobunmount.c:
+ Always allow unmount if unmount is not
+ implemented.
+
+2008-01-11 Christian Kellner <gicmo@gnome.org>
+
+ * configure.ac:
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendhttp.c:
+ * daemon/gvfsbackendhttp.h:
+ Initial attempt of writing the http backend. Not much
+ there yet only a stub.
+
+2008-01-10 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsmonitor.[ch]:
+ * daemon/gvfsbackendcomputer.c:
+ * daemon/gvfsbackendtrash.c:
+ Make GVfsMonitor API simpler for users.
+
+2008-01-10 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsmonitor.c:
+ Remove freeing of initial ref after delay.
+
+ * daemon/gvfsjobcreatemonitor.[ch]:
+ Set the monitor as result here, not only the obj path.
+ Nicer and allows better lifetime handling.
+ If returning a obj ref, keep the monitor alive for
+ some time to allow a subscribe request.
+
+ * daemon/gvfsbackendcomputer.c:
+ * daemon/gvfsbackendtrash.c:
+ Update to the new APIs
+
+2008-01-10 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.c:
+ Handle error reply from list_mounts.
+
+ * programs/gvfs-mount.c:
+ Add option to list mounts.
+ Based on patch from nf2@scheinwelt.at
+
+2008-01-09 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghaldrive.c:
+ * hal/ghalmount.c:
+ * hal/ghalvolume.c:
+ Use default fallbacks for icons
+
+2008-01-09 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountsource.[ch]:
+ Add g_mount_source_get_operation() that lets
+ you handle a remote GMountSource as if it
+ was a GMountOperation.
+
+ * common/gmountoperationdbus.c:
+ * programs/gvfs-mount.c:
+ Update to new GMountOperation APIs
+
+ * client/gdaemonfile.c:
+ * daemon/gvfsjobmountmountable.[ch]:
+ Also let you return target by uri, as not all
+ targets are from gvfs.
+
+ * daemon/gvfsbackendcomputer.c:
+ Initial cut at mount_mountable
+
+2008-01-09 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c (_g_daemon_vfs_get_mount_info_sync):
+ Better error return on not mounted.
+
+2008-01-09 Luca Ferretti <elle.uca@libero.it>
+
+ * Makefile.am:
+ * autogen.sh:
+ * configure.ac:
+
+ Reuse intltool by now, glib-gettext rules seems unable
+ to properly remove "[encoding: UTF-8]" generating
+ po/POTFILES.
+
+ * mkinstalldirs:
+
+ Removed, autogenerated by intltool
+
+2008-01-08 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.1 ===
+
+2008-01-08 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+2008-01-08 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Require glib 2.15.1
+
+2008-01-08 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ * daemon/computer.mount.in:
+ * daemon/gvfsbackendcomputer.[ch]:
+ Add initial computer backend
+
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsjobunmountmountable.[ch]:
+ Add umount_mountable calls
+
+2008-01-07 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * client/gdaemondirectorymonitor.[ch]:
+ * client/gdaemonfile.c:
+ * daemon/gvfsbackendtrash.c:
+ * programs/gvfs-monitor-dir.c:
+ Update to handle removed GDirectoryMonitor from
+ API.
+
+ * daemon/gvfsbackendsftp.c:
+ Fix warnings
+
+2008-01-07 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Remove debug spew
+
+2008-01-07 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Update to new gio API
+
+2008-01-04 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ (make_reply_stream):
+ Update to new gio API
+
+2008-01-03 Matthias Clasen <mclasen@redhat.com>
+
+ * daemon/Makefile.am: Install the .mount files
+ in /usr/share/gvfs/mounts, not in /etc/gvfs/mounts
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghalvolumemonitor.c:
+ Handle pool finalizing on unloads of hal module
+ (#507037)
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Return icons
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Use right types for file times (#506494)
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Don't return errors on EOF (#506493)
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile.am:
+ * mkinstalldirs: Added.
+ Added mkinstalldirs to svn and EXTRA_DIST ase
+ we now don't gettextize in autogen.
+
+2008-01-03 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghaldrive.c:
+ (_drive_get_description):
+ Fix plus/minus utf8 string.
+ Patch from Luca Ferretti.
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.1.0 ===
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * NEWS:
+ Update for release
+
+ * configure.ac:
+ Bump version to 0.1.0
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * autogen.sh:
+ Don't run gettextize
+
+ * programs/Makefile.am:
+ dist gvfs-less
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/main.c:
+ Fix translated "".
+
+ * hal/ghaldrive.c:
+ Encode +/- as utf8 c escapes
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Require glib 2.15.0
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsjobqueryinfo.c:
+ * programs/gvfs-copy.c:
+ * programs/gvfs-ls.c:
+ * programs/gvfs-move.c:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ Update to new file attribute names
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c:
+ * hal/ghaldrive.c:
+ * hal/ghalmount.c:
+ * hal/ghalvolume.c:
+ * programs/gvfs-mount.c:
+ Update to new unmount flag api
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * client/gdaemonvfs.c:
+ * client/gvfsfusedaemon.c:
+ Fix warnings
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ Build without cdda.
+ Patch from nf2@scheinwelt.at
+
+2007-12-19 David Zeuthen <davidz@redhat.com>
+
+ Add missing files from previous patch.
+
+ * daemon/cdda.mount.in:
+ * daemon/gvfsbackendcdda.c: (g_vfs_backend_cdda_finalize),
+ (g_vfs_backend_cdda_init), (do_mount), (try_mount), (do_unmount),
+ (get_track_num_from_name), (free_read_handle), (create_header),
+ (do_open_for_read), (paranoia_callback), (do_read),
+ (do_seek_on_read), (do_close_read), (set_info_for_track),
+ (do_query_info), (do_enumerate), (g_vfs_backend_cdda_class_init):
+ * daemon/gvfsbackendcdda.h:
+ * programs/gvfs-less:
+
+2007-12-19 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.[ch]:
+ * client/gdaemonvolumemonitor.c:
+ * hal/ghalvolumemonitor.c:
+ * hal/hal-module.c:
+ Remove spew
+ Update for new APIs
+ Don't use GDaemonVolumeMonitor if not using GDaemonVfs.
+
+ * hal/hal-pool.c:
+ Close custom dbus connection before unrefing
+
+2007-12-19 David Zeuthen <davidz@redhat.com>
+
+ Add the cdda:// backend for Compact Disc Digital Audio discs.
+
+ Allow a backend to specify the fuse name directly instead of
+ using the display name
+
+ Make GDaemonVolumeMonitor and GDaemonMount use the new
+ adopt_orphan_mount() function on GVolumeMonitor in gio. Also,
+ since a GMount now can be associated with a GVolume, implement
+ eject().
+
+ Add a new gvfs-less program.
+
+ Make gvfs-mount capable of unmounting as well.
+
+ HAL backend changes: attempt to unmount all mounts from
+ enclosing volumes and fail the ejection if one of the unmount
+ operations fails. Use new adopt_orphan_mount() from gio to
+ adopt cdda:// volumes for audio discs. Emit the 'eject-button'
+ signal on GDrive. Various other fixes.
+
+ * client/gdaemonfile.c: (g_daemon_file_find_enclosing_mount):
+ * client/gdaemonmount.c: (g_daemon_mount_finalize),
+ (g_daemon_mount_new), (g_daemon_mount_get_volume),
+ (g_daemon_mount_get_drive), (g_daemon_mount_can_eject),
+ (foreign_volume_removed), (g_daemon_mount_set_foreign_volume),
+ (eject_wrapper_callback), (g_daemon_mount_eject),
+ (g_daemon_mount_eject_finish), (g_daemon_mount_mount_iface_init):
+ * client/gdaemonmount.h:
+ * client/gdaemonvolumemonitor.c: (mount_added), (mount_removed),
+ (g_daemon_volume_monitor_init):
+ * client/gvfsfusedaemon.c: (file_handle_close_stream),
+ (free_file_handle_for_path), (mount_record_new):
+ * common/gmounttracker.c: (g_mount_info_dup), (g_mount_info_unref),
+ (g_mount_info_from_dbus):
+ * common/gmounttracker.h:
+ * configure.ac:
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.c: (g_vfs_backend_finalize),
+ (g_vfs_backend_init), (g_vfs_backend_set_fuse_name),
+ (g_vfs_backend_get_fuse_name), (g_vfs_backend_register_mount):
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsjobunmount.c: (unregister_mount_callback),
+ (send_reply):
+ * daemon/mount.c: (vfs_mount_free), (vfs_mount_to_dbus),
+ (register_mount), (list_mounts):
+ * hal/ghaldrive.c: (g_hal_drive_finalize), (hal_condition),
+ (g_hal_drive_new), (spawn_cb), (g_hal_drive_eject_do),
+ (free_unmount_mounts_op), (_eject_unmount_mounts_cb),
+ (_eject_unmount_mounts), (g_hal_drive_eject):
+ * hal/ghalmount.c: (g_hal_mount_finalize), (unmount_cb),
+ (unmount_read_error), (unmount_do), (g_hal_mount_unmount),
+ (eject_wrapper_callback), (g_hal_mount_eject),
+ (g_hal_mount_eject_finish):
+ * hal/ghalvolume.c: (g_hal_volume_finalize), (do_update_from_hal),
+ (g_hal_volume_new), (g_hal_volume_get_mount),
+ (foreign_mount_unmounted), (g_hal_volume_adopt_foreign_mount),
+ (g_hal_volume_has_foreign_mount_root), (spawn_cb),
+ (mount_foreign_callback), (g_hal_volume_mount),
+ (g_hal_volume_mount_finish), (eject_wrapper_callback),
+ (g_hal_volume_eject), (g_hal_volume_eject_finish):
+ * hal/ghalvolume.h:
+ * hal/ghalvolumemonitor.c: (adopt_orphan_mount),
+ (g_hal_volume_monitor_class_init), (update_volumes),
+ (update_mounts), (update_discs):
+ * hal/hal-device.c: (hal_device_class_init),
+ (_hal_device_hal_condition):
+ * hal/hal-device.h:
+ * hal/hal-marshal.list:
+ * hal/hal-pool.c: (hal_pool_class_init), (_hal_condition),
+ (hal_pool_new):
+ * hal/hal-pool.h:
+ * programs/Makefile.am:
+ * programs/gvfs-mount.c: (unmount_done_cb), (unmount), (main):
+
+2007-12-18 Luca Ferretti <elle.uca@libero.it>
+
+ * configure.ac: Add ALL_LINGUAS and definition for GVFS_LOCALEDIR;
+ the second one is unused by now, but could be needed, so all
+ l10n stuff in this file should be OK.
+
+2007-12-17 David Zeuthen <davidz@redhat.com>
+
+ * hal/ghalvolumemonitor.c (update_mounts): g_get_unix_mounts()
+ was renamed to g_unix_mounts_get() in gio
+
+ * hal/hal-pool.c, Makefile.am: Instead of dbus-glib-1, use the
+ function _g_dbus_connection_integrate_with_main() for mainloop
+ integration.
+
+ * hal/ghalmount.h, hal/ghalvolume.h, hal/ghaldrive.h: Use a weak
+ pointer for the volume monitor
+
+ * configure.ac: Don't require dbus-glib-1 for the hal vm backend
+
+2007-12-17 David Zeuthen <davidz@redhat.com>
+
+ * client/gdaemonmount.c (g_daemon_mount_mount_iface_init): Fix typo
+ with setting the can_eject() function
+
+2007-12-17 Bastien Nocera <hadess@hadess.net>
+
+ * daemon/gvfsbackendtrash.c: (list_trash_dirs):
+ Fix build, renamed g_get_unix_mounts to g_unix_mounts_get
+
+2007-12-17 Alexander Larsson <alexl@redhat.com>
+
+ * hal/ghaldrive.[ch]:
+ * hal/ghalmount.[ch]:
+ * hal/ghalvolume.[ch]:
+ * hal/ghalvolumemonitor.[ch]:
+ * hal/hal-device.[ch]:
+ * hal/hal-module.c:
+ * hal/hal-pool.[ch]:
+ Make types dynamic and update to support volume monitor
+ backend name and is_supported().
+
+2007-12-17 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonmount.c (g_daemon_mount_mount_iface_init):
+ Eject not supported. Make vtable NULL.
+
+2007-12-14 David Zeuthen <davidz@redhat.com>
+
+ * Makefile.am:
+ * client/gdaemonmount.c: (g_daemon_mount_get_uuid),
+ (g_daemon_mount_can_eject), (g_daemon_mount_eject),
+ (g_daemon_mount_eject_finish), (g_daemon_mount_mount_iface_init):
+ * client/gdaemonvolumemonitor.c: (get_volume_for_uuid),
+ (get_mount_for_uuid), (g_daemon_volume_monitor_class_init):
+ * configure.ac:
+ * hal/*: new files
+
+ Update to latest gio API changes and add the HAL backend for
+ volume monitoring.
+
+2007-12-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileinputstream.c:
+ * client/gvfsfusedaemon.c:
+ * common/gvfsdaemonprotocol.c:
+ * common/gvfsdaemonprotocol.h:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsjobsetattribute.c:
+ * daemon/gvfsjobsetattribute.h:
+ * programs/gvfs-info.c:
+ * programs/gvfs-ls.c:
+ Update for gio API changes (removal of GFileAttributeValue).
+
+2007-12-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * common/gmountsource.c:
+ * common/gmountsource.h:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * programs/gvfs-info.c:
+ * programs/gvfs-monitor-dir.c:
+ * programs/gvfs-monitor-file.c:
+ * programs/gvfs-mount.c:
+ * programs/gvfs-save.c:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ Update to new gio flag enum types/values
+
+2007-12-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemondirectorymonitor.c:
+ * client/gdaemondirectorymonitor.h:
+ * client/gdaemonfile.c:
+ * client/gdaemonfile.h:
+ * client/gdaemonfileenumerator.c:
+ * client/gdaemonfileenumerator.h:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileinputstream.h:
+ * client/gdaemonfilemonitor.c:
+ * client/gdaemonfilemonitor.h:
+ * client/gdaemonfileoutputstream.c:
+ * client/gdaemonfileoutputstream.h:
+ * client/gdaemonmount.c:
+ * client/gdaemonmount.h:
+ * client/gdaemonvfs.c:
+ * client/gdaemonvfs.h:
+ * client/gdaemonvolumemonitor.h:
+ * client/gvfsdaemondbus.c:
+ * client/gvfsdaemondbus.h:
+ * client/gvfsfusedaemon.c:
+ * client/gvfsurimapper.h:
+ * client/smburi.c:
+ * common/gdbusutils.c:
+ * common/gdbusutils.h:
+ * common/gmountoperationdbus.c:
+ * common/gmountoperationdbus.h:
+ * common/gmountsource.c:
+ * common/gmountsource.h:
+ * common/gsysutils.c:
+ * common/gvfsdaemonprotocol.c:
+ * common/gvfsdaemonprotocol.h:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtest.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsdaemonutils.c:
+ * daemon/gvfsjob.c:
+ * daemon/gvfsjob.h:
+ * daemon/gvfsjobcopy.h:
+ * daemon/gvfsjobcreatemonitor.h:
+ * daemon/gvfsjobdelete.h:
+ * daemon/gvfsjobenumerate.h:
+ * daemon/gvfsjobmakedirectory.h:
+ * daemon/gvfsjobmakesymlink.h:
+ * daemon/gvfsjobmount.h:
+ * daemon/gvfsjobmountmountable.h:
+ * daemon/gvfsjobmove.h:
+ * daemon/gvfsjobqueryattributes.h:
+ * daemon/gvfsjobqueryfsinfo.h:
+ * daemon/gvfsjobqueryinfo.h:
+ * daemon/gvfsjobsetattribute.h:
+ * daemon/gvfsjobsetdisplayname.h:
+ * daemon/gvfsjobtrash.h:
+ * daemon/gvfsjobunmount.h:
+ * daemon/gvfsmonitor.h:
+ * daemon/mount.c:
+ * daemon/mount.h:
+ * programs/gvfs-cat.c:
+ * programs/gvfs-copy.c:
+ * programs/gvfs-info.c:
+ * programs/gvfs-ls.c:
+ * programs/gvfs-monitor-dir.c:
+ * programs/gvfs-monitor-file.c:
+ * programs/gvfs-mount.c:
+ * programs/gvfs-move.c:
+ * programs/gvfs-rm.c:
+ * programs/gvfs-save.c:
+ * programs/gvfs-trash.c:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ * test/benchmark-posix-big-files.c:
+ * test/benchmark-posix-small-files.c:
+ Only use <gio/gio.h> include
+
+2007-12-13 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * programs/gvfs-mount.c:
+ Update for g_mount_for_location to g_file_mount_enclosing_volume change.
+
+2007-12-11 David Zeuthen <davidz@redhat.com>
+
+ Update for API changes in gio trunk.
+
+ * client/Makefile.am:
+ * client/gdaemonfile.c: (g_daemon_file_find_enclosing_mount),
+ (g_daemon_file_file_iface_init):
+ * client/gdaemonvolumemonitor.c: (get_mounts), (get_volumes),
+ (find_mount_by_mount_info), (mount_added), (mount_removed),
+ (g_daemon_volume_monitor_init), (g_daemon_volume_monitor_finalize),
+ (g_daemon_volume_monitor_class_init):
+ * client/gdaemonvolumemonitor.h:
+ * client/gvfsfusedaemon.c: (mount_record_new),
+ (mount_record_for_mount_exists), (mount_list_update),
+ (mount_tracker_mounted_cb), (mount_tracker_unmounted_cb),
+ (subthread_main):
+ * daemon/gvfsbackendtrash.c: (list_trash_dirs):
+
+2007-12-05 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ (g_daemon_vfs_init):
+ Use the new API to load the modules
+
+2007-12-05 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileenumerator.c:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ Update to gio API change
+
+2007-11-27 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * client/gdaemonvfs.c:
+ * client/gvfsfusedaemon.c:
+ * client/gvfsuriutils.h:
+ * daemon/gvfsbackend.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfschannel.c:
+ * daemon/gvfsmonitor.c:
+ * daemon/mount.c:
+ Update to build with the latest glib included
+ gio
+
+2007-11-27 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile.am:
+ * configure.ac:
+ * programs/Makefile.am:
+ * programs/gvfs-cat.c:
+ * programs/gvfs-copy.c:
+ * programs/gvfs-info.c:
+ * programs/gvfs-ls.c:
+ * programs/gvfs-monitor-dir.c:
+ * programs/gvfs-monitor-file.c:
+ * programs/gvfs-mount.c:
+ * programs/gvfs-move.c:
+ * programs/gvfs-rm.c:
+ * programs/gvfs-save.c:
+ * programs/gvfs-trash.c:
+ Moved the gio tools from gio-standalone
+
+2007-11-20 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Add comment
+
+ * daemon/gvfsbackendsmb.c:
+ Support new WOULD_MERGE error code
+
+2007-11-16 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * client/smburi.c:
+ * common/gdbusutils.c:
+ * common/gmountsource.c:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsdaemon.c:
+ * daemon/gvfsjob.c:
+ * daemon/gvfsjobdbus.c:
+ * daemon/gvfsjobopenforwrite.h:
+ * daemon/mount.c:
+ * daemon/pty_open.c:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ * test/benchmark-posix-small-files.c:
+ Code cleanups from Kjartan Maraas.
+
+2007-11-15 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.0.2 ===
+
+2007-11-15 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Require gio 0.1.2
+
+ * NEWS:
+ Update for release
+
+2007-11-15 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/Makefile.am:
+ * daemon/ftp.mount.in:
+ * daemon/gvfs-daemon.service.in:
+ * daemon/sftp.mount.in:
+ * daemon/smb-browse.mount.in:
+ * daemon/smb.mount.in:
+ * daemon/trash.mount.in:
+ Rename gvfs daemon processes to start
+ with "gvfsd". This is shorter and nicer.
+
+2007-11-14 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.h:
+ Add unmount operation and
+ unregister mount mounttracker call
+
+ * client/gdaemonvolume.c:
+ Implement client side of unmount
+
+ * daemon/Makefile.am:
+ * daemon/gvfsjobunmount.[ch]: Added.
+ Add unmount job type
+
+ * daemon/gvfsbackend.[ch]:
+ Implement unmount
+
+2007-11-14 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.c:
+ Handle NULL callback in _g_dbus_connection_call_async
+
+ * daemon/gvfsdaemon.c:
+ Re-register backends with new main daemons
+
+2007-11-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.[ch]:
+ * client/gvfsdaemondbus.c:
+ Make sure we somewhat cleanly handle the
+ various dbus daemons going down. By somewhat
+ I mean that no problem should be persistant
+ even if you might get some transient error
+ messages.
+
+ Unfortunately the only way to be able to cleanly
+ handle this involves globally ignoring SIGPIPE.
+ What can I say, unix sucks.
+
+ * common/gsysutils.c:
+ (_g_socket_receive_fd):
+ Handle errors if e.g. the fd is closed
+
+2007-11-13 Alexander Larsson <alexl@redhat.com>
+
+ * common/gsysutils.c:
+ * daemon/gvfschannel.c:
+ * daemon/gvfsdaemonutils.c:
+ * daemon/gvfsjobcopy.c:
+ * daemon/gvfsmonitor.c:
+ * daemon/gvfswritechannel.c:
+ Add required includes for solaris
+ Patch from Damien Carbery
+
+2007-11-12 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsurimapper.[ch]:
+ Make this class dynamic
+
+ * client/Makefile.am:
+ * client/gdaemonvfs.c:
+ * client/smburi.c:
+ Build smb uri mapper into module
+ (this avoids extra .so files)
+
+2007-11-12 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountspec.[ch]:
+ (g_mount_spec_new_from_data):
+ (g_mount_spec_set_with_len):
+ Add new functions
+
+ * client/Makefile.am:
+ * common/Makefile.am:
+ Update for moved files
+ Build non-shared version of common libs.
+ Ups non-shared common libs in client module.
+
+ * common/gvfsuriutils.[ch]: Removed.
+ * client/gvfsuriutils.[ch]: Added.
+ Moved uriutils to gvfs (not used by daemon)
+ Re-namespace to g_vfs_*
+
+ * common/gvfsurimapper.[ch]: Removed.
+ * client/gvfsurimapper.[ch]: Added.
+ Move UriMapper to client lib
+ Remove/Hide use of GMountSpec
+
+ * client/gdaemonvfs.c:
+ * client/smburi.c:
+ Update to the new APIs
+
+ * client/gvfsfusedaemon.c:
+ * daemon/gvfsbackendtrash.c:
+ * daemon/gvfsjobqueryfsinfo.c:
+ Fix warnings
+
+2007-11-08 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemon.c:
+ * daemon/gvfsjobmove.c:
+ * test/benchmark-common.c:
+ Fixes for solaris build.
+ Patches from Damien Carbery
+
+2007-11-07 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * daemon/gvfsbackendsftp.c:
+ Update g_memory_output_stream_set_free_on_close() to
+ g_memory_output_stream_set_free_data().
+
+2007-11-07 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ Update to new gvfs construction API
+
+2007-11-07 Alexander Larsson <alexl@redhat.com>
+
+ * common/gdbusutils.c:
+ * daemon/gvfsbackendtest.c:
+ * daemon/gvfsbackendtrash.c:
+ Ansi C fixes from Jens Granseuer
+
+2007-11-06 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * configure.ac:
+ * daemon/gvfsdaemonutils.c: (dbus_connection_send_fd):
+ * daemon/mount.c: (vfs_mount_to_dbus), (dbus_message_function):
+ Fix typo: availible -> available.
+
+2007-11-06 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Post release version bump
+
+=== gvfs 0.0.1 ===
+
+2007-11-06 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * daemon/Makefile.am:
+ * test/Makefile.am:
+ Fix make distcheck
+
+2007-11-06 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ (g_daemon_file_file_iface_init):
+ Actually export get_uri_scheme
+
+ * client/gdaemonfileinputstream.c:
+ (g_daemon_file_input_stream_query_info):
+ Set NOT_SUPPORTED error
+
+2007-11-06 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountoperationdbus.c:
+ * common/gmounttracker.c:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfschannel.h:
+ Remove use of old giotypes.h header
+
+2007-11-03 Paolo Borelli <pborelli@katamail.com>
+
+ * client/gdaemonvfs.c (get_mountspec_from_uri):
+ Do not leak the decoded uri.
+
+2007-11-02 Sebastien Bacher <seb128@ubuntu.com>
+
+ * common/Makefile.am: use the correct gmountoperationdbus.h naming
+
+2007-11-01 Christian Kellner <gicmo@gnome.org>
+
+ * client/*.[ch]:
+ * common/*.[ch]:
+ * daemon/*.[ch]:
+ * test/*.[ch]:
+ Add copyright information to source files.
+
+2007-11-01 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonvfs.[ch]:
+ Implement get_uri_scheme
+
+ * daemon/mount.c:
+ Add needed includes
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ Implement contains_file and get_relative_path
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackend.[ch]:
+ Add g_vfs_backend_get_mount_spec
+
+ * daemon/gvfsjobqueryfsinfo.c:
+ Fix indentation
+
+ * daemon/gvfsjobqueryinfo.c:
+ Implement id:fs attribute
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvolume.c:
+ Remove get_platform_id
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ Implement find_enclosing_volume
+
+ * client/gdaemonvolume.[ch]:
+ * client/gdaemonvolumemonitor.c:
+ No need to pass volume monitor when
+ createing volumes
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.[ch]:
+ Add all mount info to GMountInfo
+ Make it refcounted
+
+ * client/gdaemonvfs.[ch]:
+ * client/gdaemonfile.c:
+ * client/gdaemonvolumemonitor.c:
+ Remove GMountRef, replacing its use with
+ GMountInfo
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsjobqueryfsinfo.c:
+ Remove volume name attribute
+
+2007-10-31 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Update to new API
+
+2007-10-30 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.c:
+ Handle threads not being initialized
+
+ * daemon/gvfsjobqueryfsinfo.c:
+ Set volume name
+
+2007-10-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvolumemonitor.c:
+ Don't show not user visible mounts
+
+ * daemon/mount.c:
+ Don't give fuse mounts for non visible mounts
+ (as they don't get mounted)
+
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtrash.c:
+ Mark as not user visible
+
+2007-10-26 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.h:
+ Add registerFuse call
+
+ * client/gvfsfusedaemon.c:
+ Register with vfs daemon
+ Exit (and unmount) if daemon dies
+
+ * daemon/mount.c:
+ Hand out fuse mountpaths when availible.
+
+ * client/gdaemonvfs.[ch]:
+ * common/gmounttracker.c:
+ Handle sent fuse mountpath
+
+ * client/gdaemonfile.c:
+ Implement g_daemon_file_get_path using fuse
+ if availible.
+
+2007-10-26 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * client/gvfsfusedaemon.c:
+ Update fuse daemon to use the giomodule instead of
+ linking to a copy of the code. The old way was
+ problematic with the module code being a dynamic
+ type in the module and not in the fuse daemon.
+
+2007-10-25 Alexander Larsson <alexl@redhat.com>
+
+ * client/smburi.c:
+ * common/gvfsurimapper.[ch]:
+ Make to_uri_scheme return const string.
+
+ * client/gdaemonfile.[ch]:
+ * client/gdaemonvfs.[ch]:
+ Add _g_daemon_vfs_mountspec_has_uri_scheme and use it to
+ implement g_file_has_uri_scheme
+
+2007-10-24 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountsource.c:
+ (g_mount_source_ask_password):
+ Increase password dialog timeout to 30 minutes
+
+2007-10-24 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountspec.c:
+ (g_mount_spec_set_mount_prefix):
+ Actually assign the mount_prefix in the GMountSpec
+
+2007-10-23 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * client/Makefile.am:
+ Change the GIO module dir to $(libdir)/gio/modules as was
+ done in GIO.
+
+2007-10-23 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonvfs.c:
+ * common/gmountspec.[ch]:
+ Ensure GDaemonFile mount specs are actually unique.
+ When a non-unique mount spec was finalized any unique
+ version of the same was removed from the hashtable.
+
+2007-10-23 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ (_g_daemon_vfs_get_uri_for_mountspec):
+ Better handling for default types.
+ (Handle hostname, port and username)
+
+2007-10-22 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.c:
+ * common/gvfsuriutils.[ch]:
+ * daemon/gvfsbackendtrash.c:
+ Update to use the gurifuncs.h from gio.
+ Fix filename parsing to handle ~/x
+
+2007-10-19 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackend.[ch]:
+ Rename set_icon -> set_icon_name
+ Add getter for icon_name and display_name
+
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ Update for API changes
+ Set display name for in fileinfo
+
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendtrash.c:
+ Update for API changes
+
+
+2007-10-19 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ (g_daemon_file_hash): Faster hash, since mount_spec is unique
+ (g_daemon_file_equal): Compare mount spec too
+
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ Set volume display names and icons
+ Set content type and icon for files
+
+2007-10-19 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmounttracker.[ch]:
+ * client/gdaemonvfs.c:
+ * daemon/mount.c:
+ Add user_visible to mount info
+ Reorder args so that new stuff comes at the end
+
+ * daemon/gvfsbackend.[ch]:
+ Add user_visible setting
+ Fix up various setters that set the wrong variable
+
+ * daemon/gvfsbackendtrash.c:
+ Add icon and better display name
+
+2007-10-19 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonvfs.[ch]:
+ * client/gdaemonvolume.c:
+ * client/gdaemonvolumemonitor.[ch]:
+ Implement using DEFINE_DYNAMIC_TYPE
+ Actually register GDaemonVolumeMonitor in giomodule
+
+ * common/gmounttracker.c:
+ Update to the on-dbus format for mounts
+
+2007-10-19 Alexander Larsson <alexl@redhat.com>
+
+ * client/smburi.c (smb_to_uri):
+ No port by default
+
+2007-10-16 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ (g_daemon_file_get_parent):
+ Fix get_parent to handle files that are in the root directory
+
+2007-10-16 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.[ch]:
+ Make sending icons actually work
+
+ * daemon/gvfsbackendtrash.c:
+ Set icon for toplevel
+
+ * daemon/gvfsmonitor.c:
+ Initialize error before call
+
+2007-10-12 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsdaemon.c:
+ Build fixes
+ Patch from Milosz Derezynski <internalerror@gmail.com>
+
+2007-10-10 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Support file monitor on trash:/// (for icon)
+
+2007-10-10 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Add support for directory monitor on root dir
+
+2007-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Correctly handle len arg in unescape_pathname
+
+2007-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Nicer filenames for things in the home trash.
+ This is the common case, so lets make them look nice.
+
+2007-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Check for trash dirs in fork to avoid getting stuck
+ on e.g. hanged nfs dirs
+
+2007-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * client/Makefile.am:
+ * client/gdaemonfile.c:
+ * client/gdaemonfilemonitor.[ch]:
+ Implement file monitor in client
+
+ * common/gvfsdaemonprotocol.h:
+ * daemon/gvfsbackend.c:
+ Implement file monitor in daemon
+
+ * daemon/gvfsbackendtrash.c:
+ Implement file monitor in trash backend
+ Make trash filename escaping nicer
+
+2007-10-09 Alexander Larsson <alexl@redhat.com>
+
+ * configure.ac:
+ Pull in gio-unix-2.0
+
+ * daemon/gvfsbackendtrash.c:
+ Use GUnixMounts instead of volume monitor
+ This shows *all* mounts and avoids unnecessary stuff
+
+2007-10-08 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsdaemonprotocol.h:
+ Add defines for monitoring
+
+ * client/Makefile.am:
+ * client/gdaemondirectorymonitor.[ch]:
+ * client/gdaemonfilemonitor.[ch]:
+ * client/gdaemonfile.c:
+ Add daemon directory monitor and initial work on file monitor
+
+ * client/gdaemonfileenumerator.c:
+ Make path_counter private
+ Return DBUS_HANDLER_RESULT_HANDLED when handling messages.
+
+ * client/gdaemonvfs.[ch]:
+ Make _g_mount_ref_ref "public"
+
+ * client/gvfsdaemondbus.c:
+ Handle NULL callbacks for async calls
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.[ch]:
+ * daemon/gvfsjobcreatemonitor.[ch]:
+ Add create_dir_monitor and create_file_monitor.
+ Add g_vfs_backend_get_daemon
+
+ * daemon/gvfsmonitor.[ch]:
+ Helper code for monitors
+
+ * daemon/gvfsbackendtrash.c:
+ Implement directory monitor for trash dirs
+
+2007-10-08 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * client/gdaemonvfs.c: (g_daemon_vfs_finalize),
+ (g_daemon_vfs_init), (fill_supported_uri_schemes),
+ (g_daemon_vfs_get_supported_uri_schemes),
+ (g_daemon_vfs_class_init):
+ * client/smburi.c: (smb_to_uri_scheme),
+ (g_vfs_uri_mapper_smb_class_init):
+ * common/gvfsdaemonprotocol.h:
+ * common/gvfsurimapper.c: (g_vfs_uri_mapper_to_uri_scheme):
+ * common/gvfsurimapper.h:
+ * daemon/mount.c: (list_mount_types), (dbus_message_function):
+ Implement get_supported_uri_schemes method and add a GVfsUriMapper
+ method to map a mount spec to an URI scheme.
+
+2007-10-05 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendtrash.c:
+ Add delete support to trash
+
+2007-10-04 Alexander Larsson <alexl@redhat.com>
+
+ * common/gvfsuriutils.c:
+ (g_uri_unescape_string):
+ Allow NULL end pointer
+
+ * daemon/gvfsjob.[ch]:
+ Add cancellable to GVfsJob for backends that want one
+
+ * daemon/gvfsjobenumerate.[ch]:
+ * daemon/gvfsjobqueryinfo.[ch]:
+ Also store attribute in string form.
+ Needed if you want to pass it on into gio.
+
+ * daemon/Makefile.am:
+ * daemon/gvfsbackendtrash.[ch]:
+ * daemon/trash.mount.in: Added.
+ Added trash backend
+
+2007-10-04 Alexander Larsson <alexl@redhat.com>
+
+ * TODO:
+ * client/gdaemonfile.c:
+ * client/gvfsfusedaemon.c:
+ * daemon/gvfsbackend.h:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsjobopenforwrite.[ch]:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ Add GFileCreateFlags flag to open for write.
+ No actual backend support yet though.
+
+2007-10-02 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * client/gdaemonfile.c: (g_daemon_file_append_to),
+ (g_daemon_file_create), (g_daemon_file_replace):
+ * test/benchmark-gvfs-big-files.c: (create_file):
+ * test/benchmark-gvfs-small-files.c: (create_file): Update to API
+ changes in gio.
+
+ * daemon/gvfschannel.c:
+ * daemon/gvfsreadchannel.c:
+ * daemon/gvfswritechannel.c:
+ * daemon/main.c:
+ Drop unecessary includes.
+
+2007-09-29 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * configure.ac: Revert accidentally included local change.
+
+2007-09-29 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * configure.ac: Update to the new pkg-config filename.
+ * gio-standalone.pc.in: Remove pkg-config file that belongs to gio.
+
+2007-09-27 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * daemon/gvfsbackendftp.c: (do_replace), (do_query_info),
+ (do_query_fs_info), (do_enumerate):
+ Update signatures for API changes in gio.
+
+2007-09-25 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsdaemondbus.c:
+ Clear VfsConnectionData on creation
+ (fixes read of uninitialized data on thread shutdown)
+
+ * daemon/sftp.mount.in:
+ Correct the type to "sftp"
+
+2007-09-25 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/mount.c:
+ Return NOT_SUPPORTED error for unsupported uri types
+
+2007-09-25 Alexander Larsson <alexl@redhat.com>
+
+ * client/gvfsfusedaemon.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ Update for G_IO_ERROR_NOT_MOUNTABLE_FILE name change
+
+2007-09-25 Alexander Larsson <alexl@redhat.com>
+
+ * common/gmountoperationdbus.[ch]:
+ * common/gmounttracker.[ch]:
+ Pass in DBusConnection to use instead of using default one
+
+ * client/gdaemonfile.c:
+ * client/gdaemonvfs.[ch]:
+ * client/gvfsdaemondbus.c:
+ Use private dbus connection even for async calls, since the
+ mainloop integration is conflicting with dbus-glib.
+ This is a temporary measure until this is solved in a better way.
+
+ * client/gdaemonvolumemonitor.c:
+ * client/gvfsfusedaemon.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ Update to the API changes
+
+2007-09-25 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * client/gdaemonvfs.c: (g_daemon_vfs_finalize):
+ Don't unref wrapped_vfs as it's just a pointer to the single instance
+ return value of g_vfs_get_local().
+
+2007-09-25 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * client/gdaemonfile.c: (g_daemon_file_resolve_relative_path),
+ (g_daemon_file_file_iface_init):
+ * test/benchmark-gvfs-big-files.c: (create_file):
+ * test/benchmark-gvfs-small-files.c: (create_file):
+ Update for API change in GIO. g_file_resolve_relative was renamed
+ to g_file_resolve_relative_path.
+
+2007-09-25 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * common/gmountspec.c: (g_mount_spec_to_dbus_with_path):
+ * common/gvfsdaemonprotocol.c: (_g_dbus_append_file_attribute),
+ (_g_dbus_append_file_info), (_g_dbus_append_attribute_info_list):
+ * daemon/mount.c: (vfs_mount_to_dbus):
+ Don't pass the contained signature when creating a DBus struct. Since
+ DBus 1.1.0 this will lead to an assertion. The signature will filled
+ automatically while adding values to the struct.
+
+2007-09-17 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfile.c:
+ * client/gdaemonfileinputstream.c:
+ * client/gdaemonfileoutputstream.c:
+ * client/gvfsfusedaemon.c:
+ * common/gvfsdaemonprotocol.h:
+ * daemon/Makefile.am:
+ * daemon/gvfsbackend.[ch]:
+ * daemon/gvfsbackendftp.c:
+ * daemon/gvfsbackendsftp.c:
+ * daemon/gvfsbackendsmb.c:
+ * daemon/gvfsbackendsmbbrowse.c:
+ * daemon/gvfsbackendtest.c:
+ * daemon/gvfsjobenumerate.h:
+ * daemon/gvfsjobgetfsinfo.[ch]: Removed.
+ * daemon/gvfsjobgetinfo.[ch]: Removed.
+ * daemon/gvfsjobqueryfsinfo.[ch]: Added.
+ * daemon/gvfsjobqueryinfo.[ch]: Added.
+ * daemon/gvfsjobsetattribute.[ch]:
+ * test/benchmark-gvfs-big-files.c:
+ * test/benchmark-gvfs-small-files.c:
+ Update with the get_info -> query_info rename in gio
+
+2007-09-17 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Update to new GDataInputStream function names
+
+2007-09-14 Alexander Larsson <alexl@redhat.com>
+
+ * client/gdaemonfileoutputstream.c:
+ (g_daemon_file_output_stream_get_etag):
+ Update to new get_etag API.
+
+2007-09-14 Alexander Larsson <alexl@redhat.com>
+
+ * daemon/gvfsbackendsftp.c:
+ Add etag support for close on write
+
+I stopped tracked changes here. Look at "git log" instead.
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * gfilesimple.[ch]:
+ Move GFileSimple struct into c file
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * gfile.[ch]:
+ Add follow_symlinks argument to get_info
+
+ * gfileinfo.[ch]:
+ Some mask fixes
+
+ * gfilesimple.c:
+ More implementation work
+
+ * glocalfileoutputstream.[ch]:
+ Implement set_original_mtime and set_create_backup
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile:
+ Add gfilesimple
+
+ * gfile.[ch]:
+ Add g_file_copy()
+ Finish rename to parse_name
+ Remove set_keep_open for now
+
+ * gfilesimple.[ch]:
+ Initial skeleton for GFileSimple
+ Handle parse names
+
+ * gvfssimple.c:
+ Handle parse names
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * gfileenumerator.c:
+ * gfileinfo.c:
+ * gfileinputstream.c:
+ * gfileoutputstream.c:
+ * ginputstream.c:
+ * glocalfileinputstream.c:
+ * glocalfileoutputstream.c:
+ * goutputstream.c:
+ * gvfssimple.c:
+ Use macro-created parent_class
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * gfile.c:
+ * gvfs.[ch]:
+ * gvfssimple.c:
+ Clean up parse_name names.
+
+2006-09-28 Alexander Larsson <alexl@redhat.com>
+
+ * gfile.[ch]:
+ Add request flags & attributes
+ Use FileStreams
+
+ * gfileinputstream.h:
+ * gfileoutputstream.h:
+ Fix G_TYPE_... defines
+
+ * glocalfileoutputstream.c:
+ Small cleanups and mention gedit.
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * gfileinfo.[ch]:
+ Added g_file_info_new, g_file_info_set_from_stat
+
+ * glocalfileinputstream.c:
+ * glocalfileoutputstream.c:
+ Implemented get_file_info.
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * glocalfileoutputstream.c:
+ Update implementation of final mtime
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * gfileinfo.h:
+ * gfileinputstream.[ch]:
+ * gfileoutputstream.[ch]:
+ Flags & attributes in get_file_info
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile:
+ * ginputstreamfile.[ch]:
+ * goutputstreamfile.[ch]:
+ * glocalfileinputstream.[ch]:
+ * glocalfileoutputstream.[ch]:
+ Rename local file streams and make them
+ inherit from FileInput/OutputStream
+
+ * test.c:
+ Update
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile:
+ * gfileinputstream.[ch]:
+ * gfileoutputstream.[ch]:
+ Add new classes.
+
+ * gfileinfo.[ch]:
+ Add flags, symlink_target and edit_name
+
+ * ginputstream.[ch]
+ * goutputstream.[ch]:
+ Export close/pending state a bit
+
+ * gvfserror.h:
+ Add NOT_SUPPORTED
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * ginputstream.c:
+ * goutputstream.c:
+ Wrap async callback to automatically handle
+ setting of pending, closed and ref/unref of the stream.
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ reviewed by: <delete if not using a buddy>
+
+ * ginputstream.c: (read_async_callback_wrapper),
+ (g_input_stream_read_async), (skip_async_callback_wrapper),
+ (g_input_stream_skip_async), (close_async_callback_wrapper),
+ (g_input_stream_close_async), (read_op_report), (read_op_free),
+ (g_input_stream_real_read_async), (skip_op_report), (skip_op_free),
+ (g_input_stream_real_skip_async), (close_op_report),
+ (close_op_free), (g_input_stream_real_close_async):
+ * goutputstream.c: (write_async_callback_wrapper),
+ (g_output_stream_write_async), (flush_async_callback_wrapper),
+ (g_output_stream_flush_async), (close_async_callback_wrapper),
+ (g_output_stream_close_async):
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * ginputstream.[ch]:
+ Update of close and pending handling.
+
+ * goutputstream.[ch]:
+ Implement default async version
+
+2006-09-27 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile:
+ Add output file streams
+
+ * ginputstream.c: (g_input_stream_is_cancelled):
+ Cleanup
+
+ * ginputstreamfile.[ch]:
+ remove get_fd.
+
+ * goutputstream.[ch]:
+ Add g_output_stream_is_cancelled
+ Add padding
+ Add cancel_async
+
+ * goutputstreamfile.[ch]:
+ Add new class
+
+ * gvfserror.h:
+ Add new errors
+
+ * test.c:
+ Some tests
+
+2006-09-26 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile:
+ Add gthread-2.0
+
+ * ginputstream.h:
+ add async_skip and is_cancelled.
+
+ * ginputstream.c:
+ Implement async fallbacks using thread
+
+ * ginputstreamfile.c:
+ Handle cancellation
+
+ * gioscheduler.c:
+ Schedule cancelled jobs first
+ Fix out-of-lock reads of job
+ Add g_io_job_mark_done().
+
+ * gioscheduler.h:
+ Add g_io_job_mark_done().
+
+ * test.c:
+ Add some stream tests
+
diff --git a/trunk/INSTALL b/trunk/INSTALL
new file mode 100644
index 00000000..f10b3409
--- /dev/null
+++ b/trunk/INSTALL
@@ -0,0 +1,3 @@
+The ObexFTP backend requires the obex-data-server D-Bus service in
+addition to the dependencies listed in the configure. See:
+http://wiki.muiline.com/obex-data-server
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
new file mode 100644
index 00000000..0bc82219
--- /dev/null
+++ b/trunk/MAINTAINERS
@@ -0,0 +1,8 @@
+Alex Larsson
+E-mail: alexl@redhat.com
+Userid: alexl
+
+Christian Kellner
+E-mail: gicmo@gnome.org
+Userid: gicmo
+
diff --git a/trunk/Makefile.am b/trunk/Makefile.am
new file mode 100644
index 00000000..826a35ce
--- /dev/null
+++ b/trunk/Makefile.am
@@ -0,0 +1,24 @@
+NULL =
+
+SUBDIRS = \
+ common \
+ client \
+ daemon \
+ monitor \
+ gconf \
+ po \
+ programs \
+ test \
+ $(NULL)
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+
+EXTRA_DIST = \
+ MAINTAINERS \
+ $(NULL)
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update \
+ $(NULL)
diff --git a/trunk/NEWS b/trunk/NEWS
new file mode 100644
index 00000000..72da8c5a
--- /dev/null
+++ b/trunk/NEWS
@@ -0,0 +1,360 @@
+Major changes in 1.2.0
+======================
+* sftp: Don't hang if ssh no authentication method availible
+* Don't leak file monitors
+* computer: don't show shadowed mounts
+
+Major changes in 1.1.8
+======================
+* Fix crashers and leaks
+* Handle file:// uris with anchors in gvfs-open
+* fuse: Support ftruncate to the current file size
+* escape/unescape hostname part in uris, allowing spaces in e.g. smb domains
+* hal: Fix "No mount object" error on mount
+* Change details of the new .xdg-volume-info file format
+* Fix races in cancellation of gvfs streams
+* Remove debug spew from backends
+* ftp: Fix anonymous login
+* gphoto2: Ignore broken storages with no capacity
+* Don't globally modify COMP_WORDBREAKS in bash completion script
+* Don't ask for username when getting ssh key passphrase
+
+Major changes in 1.1.7
+======================
+* Fix build on some platforms
+* ftp: Fix short read errors
+* gphoto2: Make it work on iphone
+* sftp: Fix symlink creation
+* fuse: Better support of truncation, fixing OOo save
+* proxy monitors: Support mount operations, etc
+* gvfs-mount: add --device commandline support
+* sftp: Fix protocol bug that made some servers not work
+* general support for query_info over streams, implemented for smb, sftp
+* Initial support for .xdg-volume-info reading
+
+Major changes in 1.1.6
+======================
+* Fix crashes
+* trash: Better messages
+* Clean up glib and gtk includes
+* archive: Build with later versions of libarchive
+* dav: Fix folder creation
+* dav: Fix redirection when user is specified in url
+* http: fix error propagation
+* sftp: Try to preserve ownership when replacing a file
+
+Major changes in 1.1.5
+======================
+* network: Pick up SMB shares from zeroconf
+* obexftp: Write support for
+* obexftp: Support obexftp over usb
+* trash: Don't follow symlinks on delete
+* fix crashes
+
+Major changes in 1.1.4
+======================
+* Trash performance fixes
+* Fuse performance fixes
+
+Major changes in 1.1.3
+======================
+* ftp: fix limited number of connections causes commands to fail (#565504)
+* trash: fix parallel build doesn't work (#562955)
+* trash: add trash::orig-path and trash::deletion-date info
+* trash: set files to mode 700 before deleting to deal with users trashing read-only directories
+* smb-browse: browsing authentication support (#524485)
+* smb-browse: make backend not automounted anymore
+
+Major changes in 1.1.2
+======================
+* New trash backend
+* Use the new shadow mount facility in gio
+* gphoto2: Use shadow mounts
+* obex: Fix icon for root directory
+* http: Fix major memory leak
+* http: Support proxies
+
+Major changes in 1.1.1
+======================
+* Reverse map FUSE pathnames to gvfs locations
+* Fix crashes
+* Show better icon info in gvfs-info
+* Support custom icons for gvfs backends
+* dav: support uris (dav+sd://) which specify dns-sd services instead of resolved ip+port
+* ftp: Fix time parsing
+* ftp: Show username in auth dialog if specified in uri
+* ftp: Support UTF8 server feature
+* ftp: Use LIST -a instead of LIST on unix servers
+* fuse: Fix major race in that caused crashes
+* fuse: Set st_blocks so that e.g. the "du" command works
+* gphoto: use custom icons for faster thumbnails
+* obexftp: Port to bluez 4 API
+* sftp: If name specified in mount, use in name too so that fuse paths are unique
+* sftp: Support /etc/favicon.png
+* smb: Don't ask for password twice if cancelled
+* smb: support setting timestamp
+
+Major changes in 0.99.7
+=======================
+
+* Go back to using powers of 10 instead of powers of 2 for display sizes.
+ This means we will agree with printed sizes for most devices (e.g. memory
+ sticks will now correctly report "64MB volume" instead of previous
+ "61.7MB volume").
+
+* Bug fixes:
+ 546971 - rhythmbox crashed when ejecting an ipod device
+ 550858 - Export CD-Text info via xattrs
+
+* Translation updates:
+ nb.po (Kjartan Maraas), nl.po (Wouter Volsterlee), pt.po (Duarte Loreto),
+ cs.po (Petr Kovar)
+
+Major changes in 0.99.6
+=======================
+
+* Better cross-backend copy/move logic. Now will perform an actual file
+ system move if possible, even when the source and target are handled
+ by different backends (e.g. trash and local).
+* Now requires libsoup >= 2.23.91.
+
+* Bug fixes
+ 548841 - Incorrect usage of plural forms in gphoto backend
+ 547133 - Getting mtime over http backend is broken
+ 538573 - lastmodified uses ISO 8601 date/time where it should use http-date
+ 549253 - error path leaks
+ 549553 - gvfs mangles uri for unhandled schemes
+ 550100 - gio uses 10^3 base (SI) for volume names
+ 529971 - Restore from trash appears to do a file copy
+ RH 460223 - gnome-mount no longer automatically opens LUKS-encrypted
+ partitions
+
+* Translation updates:
+ nl.po (Wouter Bolsterlee), gl.po (Ignacio Casal Quinteiro), es.po
+ (Jorge Gonzalez), pt_BR.po (Og Maciel), et.po (Priit Laes), eu.po
+ (Inaki Larranaga Murgoitio), th.po (Theppitak Karoonboonyanan), ja.po
+ (Takeshi AIHANA), vi.po (Nguyễn Thái Ngọc Duy), fr.po (Robert-André
+ Mauchin), he.po (Yair Hershkovitz), nb.po (Kjartan Maraas), mk.po
+ (Jovan Naumovski), de.po (Hendrik Richter), ga.po (Seán de Búrca),
+ zh_HK.po (Chao-Hsiung Liao), zh_TW.po (Chao-Hsiung Liao), sv.po
+ (Daniel Nylander)
+
+Major changes in 0.99.5
+=======================
+
+* FTP backend now restores file permissions when replacing a file.
+* Miscellaneous unreported bug fixes.
+
+* Bug fixes
+ 41852 - Items should be restored to orig. name when moved out of trash
+ 546300 - g_file_replace_async doesn't allow NULL etag
+
+* Translation updates:
+ be@latin (Ihar Hrachyshka), es (Priit Laes, Jorge Gonzalez),
+ th (Theppitak Karoonboonyanan), pt_BR (Og Maciel), pl (Tomasz
+ Dominikowski), ml (Praveen Arimbrathodiyil), pt (Duarte Loreto),
+ fi (Ilkka Tuohela), zh_HK (Chao-Hsiung Liao), zh_TW (Chao-Hsiung Liao),
+ cs (Petr Kovar), gl (Ignacio Casal Quinteiro), ja (Takeshi AIHANA),
+ he (Yair Hershkovitz), gu (Sweta Kothari), ar (Djihed Afifi)
+
+
+Major changes in 0.99.4
+=======================
+
+* Require glib >= 2.17.6
+* Support und update serialization of GEmblem and GEmblemedIcon
+* Add x-content/* support to daemon mounts
+* Use standard icon names
+
+* Bug fixes
+ 545695 – any new volume is mounted twice
+ 545489 – Nautilus hangs when inserting a CD
+ 544008 – g_daemon_file_replace_async mode err
+ 543552 – gvfs-fuse-daemon crashes if dbus dies
+ 528891 – Handle URI schemes case insensitive
+ 525779 – Dont look for trashs dir on sys mounts
+ 545968 – leaks xml documents in error cases
+ 545966 – Disallow net access to WebDAV xml parser
+ 509740 – Trash icon not updated ..
+ 539167 – Use g_set_error_literal where appropriate
+ 528848 – [PATCH] statfs lies
+ 518284 – need to add i18n on module branching
+
+* Translation updates:
+ it (Luca Ferretti), gl (Ignacio Casal Quinteiro), es (Jorge Gonzalez)
+ ja (Takeshi AIHANA), ar (Khaled Hosny), pt_BR (Vladimir Melo),
+
+
+Major changes in 0.99.3
+=======================
+* Fix frequent crasher in volume monitor
+
+Major changes in 0.99.2
+* Move hal and gphoto volume monitors out of process
+* Fix recursive copying
+* Require glib >= 2.17.4
+* Make the fuse daemon more reliable
+* Many smaller bugfixes
+* et (Ivar Smolin), vi (Clytie Siddall),
+ ar (Djihed Afifi, Khaled Hosny)
+
+Major changes in 0.99.1:
+* Fix directory copy/delete problems
+* Fuse daemon robustness fixes
+* Allow mounting non-standard ISO images
+* Better username/domain tests on mount spec
+* Require gphoto >= 2.4.0
+* Fix strdup()/g_free() confusion
+* Use consistent translatable strings for mount and volume
+* Plug some memory leaks
+* Many smaller bug fixes
+* Translation updates:
+ ar (Djihed Afifi, Khaled Hosny), bg (Alexander Shopov),
+ et (Ivar Smolin), he (Yair Hershkovitz),
+ nb (Kjartan Maraas), tr (Baris Cicek), vi (Clytie Siddall)
+
+Major changes in 0.2.2:
+* Respect the giomoduledir provided in gio package config file
+* Better mount icon and name for archive backend
+* Fix crashes with cancelled stream ops
+* Fix race that caused a mount to hang for a client
+* Implement async query_filesystem_info
+* Fix minor leaks
+* trash: Correct display names for directories
+* sftp: Kerberos support
+* smb: Port to new samba 3.2.0 API (backwards compat)
+* sftp: Handle overwrites correctly (was silent overwrite)
+
+Major changes in 0.2.1:
+* Added archive backend
+* Implement most of the async functions in GDaemonFile
+* Correctly handle usernames in uris for ftp://
+* Ftp fixes
+* Webdav fixes
+* Add gvfs-rename command line utility
+* Fix cancellation
+* OpenBSD fixes
+* smb: hide dot files
+* Enviroment variable to disable fuse backend at runtime
+
+Major changes in 0.2.0:
+* Fix crashes
+* Build and portability fixes
+* Better mime icons for remote shares
+* Don't show mounts and volumes outside /media
+* Don't automount gphoto mounts
+* Translate cd disc names
+* ftp: Updates
+* obex: Give better error message on broken phones
+* sftp: Allow setting permissions
+* dav: Correct mount name, file icons and file types
+
+Major changes in 0.1.11:
+* Correctly free mounts
+* Disable debug log
+
+Major changes in 0.1.10:
+* Fix volume monitor change reporting
+* Fix timeout during automount
+
+Major changes in 0.1.9:
+* Added ftp backend
+* Added obexftp backend
+* Locking fixed for volume monitors
+* Better bash completion
+* Better webdav support
+* Allow backends to specify uri details in .mount file
+* Fix leaks and crashes
+* Fix icon for audio cds
+
+Major changes in 0.1.8:
+* Update for gio API changes
+* Add gphoto2 backend
+* Add network: and dns-sd: backend support
+* Http and webdav backend updates
+* Keyring support
+* Fix crashes and deadlocks
+* Add trash::item-count attribute to trash:///
+* Fix smb reads > 65535 bytes breaking on some servers
+* Fix cancellation race in reading
+* Fill in thumbnail info for backends
+* sftp: Handle host identity changes
+* Enable translations everywhere
+* Add bash completion support for command line apps
+* Fix handling of blank cds and audio cds
+* Support port in sftp uris
+
+Major changes in 0.1.7:
+* Update for gio API changes
+* Add gconf based implementation of
+ g_app_info_get_default_for_uri_scheme
+* Fix crashes
+* Allow navigation with http uris
+* Better file read performance with readahead and
+ large block reads
+* Lots of bugs fixed in trash backend
+* Pick up cdrom icons from autorun.inf
+* Add "filesystem" file to computer://
+* Fix renaming in sftp and smb
+
+Major changes in 0.1.6:
+* Add files missing in the released 0.1.5 tarball
+
+Major changes in 0.1.5:
+* Update to work with latest glib
+* Fix sftp error handling on reading directories
+* Use correct file info attribute name style
+* Add gvfs-mkdir app
+* hal: Don't show drives if all volumes are hidden
+* Enable translations
+
+Major changes in 0.1.4:
+* Update to work with latest glib
+* Fix compiler warnings
+
+Major changes in 0.1.3:
+* Various fixes to hal volume monitor
+* Make gvfsd reload config on SIGUSR1
+* Updates to http/dav backends
+* Port http backend to libsoup 2.4.
+* Initial burn:/// backend
+* Add ssh: alias for sftp:
+* Fix fuse mount
+* Automount fuse on startup of daemon
+* Various bugfixes
+
+Major changes in 0.1.2:
+* Switch to intltool fro translation setup
+* Update to latest gio APIS
+* Add mount list option to gvfs-mount
+* Specify fallback icons in hal backend
+* Implement more of computer: backend
+* Initial http backend
+* Fix get_relative_path bug on root paths
+
+Major changes in 0.1.1:
+* Use gio from glib (glib 2.15.1 required)
+* Fix translation issues
+* Fix various sftp backend issues
+* Move .mount files to /usr/share/gvfs/mounts
+* Add initial computer:/// backend
+
+Major changes in 0.1.0:
+* Use gio from glib (glib 2.15.0 required)
+* Update to API changes in gio
+* add cdda backend
+* add hal volume monitor
+
+Major changes in 0.0.2:
+* Updated to work win gio-standalone 0.1.2
+* Build fixes on various platforms
+* Don't link client lib to libgvfscommon.so
+* Change how the uri mapper works
+* Integrate standard uri mappers (i.e. smb) into client libs
+ (You might need to remove $prefix/lib/gvfs/modules/libsmb.so
+ from an older version if you install this)
+* Cleanly handle when gvfs daemons die, without
+ crashing the app
+* Implement unmounting
+* Rename master daemon to "gvfsd" and mount daemons to
+ names like "gvfsd-sftp".
diff --git a/trunk/README b/trunk/README
new file mode 100644
index 00000000..dc4de7a8
--- /dev/null
+++ b/trunk/README
@@ -0,0 +1,21 @@
+gvfs is a userspace virtual filesystem designed to work with the i/o
+abstractions of gio (a library availible in glib >= 2.15.1). It
+installs several modules that are automatically used by applications
+using the APIs of libgio. There is also fuse support that allows
+applications not using gio to access the gvfs filesystems.
+
+
+The gvfs model differs from e.g. gnome-vfs in that filesystems must
+be mounted before they are used. There is a central daemon (gvfsd)
+that handles coordinting mounts, and then each mount is (typically)
+in its own daemon process (although mounts can share daemon process).
+
+gvfs comes with a set of backends, including trash support, sftp,
+smb, http, dav and others. More backends are planned.
+
+gvfs also contains modules for gio that implement hal volume monitors
+and the gnome uri-scheme handler configuration.
+
+There is a set of command line programs starting with "gvfs-" that
+lets you run commands (like cat, ls, stat, etc) on files in the gvfs
+mounts.
diff --git a/trunk/TODO b/trunk/TODO
new file mode 100644
index 00000000..523051b9
--- /dev/null
+++ b/trunk/TODO
@@ -0,0 +1,32 @@
+Implement the rest of the mountable GDaemonFile ops:
+ unmount_mountable
+ eject_mountable
+
+implement readahead in GVFSReadStream, time difference
+
+implement seek & truncate
+
+implement get_file_info for GFileInputStreamDaemon, needs marshalling attributes over custom protocol
+
+finish implementing copy progress callbacks
+
+implement stuff in GDaemonVolume / GDaemonVolumeMonitor
+
+convert GDaemonFiles to fuse paths on request
+
+detect fuse paths and reverse map back to GDaemonFile
+
+remove owners from bus_name_map when they fail
+
+smb support for smbc_getxattr!
+smb - handle server going down
+
+add trash:/// support
+
+decide exactly how to handle not-mounted errors and make sure its consistent.
+mount daemons should re-register when new owner for vfs daemon.
+
+Make built-in uri parsers link into gvfs shared lib instead of using a module
+ (smb is a shared lib atm to make sure that works)
+
+Implement GFileCreateFlags in backends as possible
diff --git a/trunk/autogen.sh b/trunk/autogen.sh
new file mode 100755
index 00000000..4f24b3b9
--- /dev/null
+++ b/trunk/autogen.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+PROJECT=GVfs
+TEST_TYPE=-f
+FILE=client/gdaemonvfs.h
+
+DIE=0
+
+have_libtool=false
+if libtoolize --version < /dev/null > /dev/null 2>&1 ; then
+ libtool_version=`libtoolize --version | sed 's/^[^0-9]*\([0-9.][0-9.]*\).*/\1/'`
+ case $libtool_version in
+ 1.4*|1.5*|2.2*)
+ have_libtool=true
+ ;;
+ esac
+fi
+if $have_libtool ; then : ; else
+ echo
+ echo "You must have libtool 1.4 installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+ DIE=1
+fi
+
+(intltoolize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have intltool installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnome.org/pub/GNOME/sources/intltool"
+ DIE=1
+}
+
+(gtkdocize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have gtk-doc installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnome.org/pub/GNOME/sources/gtk-doc/"
+ DIE=1
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+ DIE=1
+}
+
+if automake --version < /dev/null > /dev/null 2>&1 ; then
+ AUTOMAKE=automake
+ ACLOCAL=aclocal
+else
+ echo
+ echo "You must have automake 1.7.x installed to compile $PROJECT."
+ echo "Install the appropriate package for your distribution,"
+ echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+ DIE=1
+fi
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+if test -z "$AUTOGEN_SUBDIR_MODE"; then
+ if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+ fi
+fi
+
+if test -z "$ACLOCAL_FLAGS"; then
+
+ acdir=`$ACLOCAL --print-ac-dir`
+ m4list="glib-2.0.m4 glib-gettext.m4"
+
+ for file in $m4list
+ do
+ if [ ! -f "$acdir/$file" ]; then
+ echo "WARNING: aclocal's directory is $acdir, but..."
+ echo " no file $acdir/$file"
+ echo " You may see fatal macro warnings below."
+ echo " If these files are installed in /some/dir, set the ACLOCAL_FLAGS "
+ echo " environment variable to \"-I /some/dir\", or install"
+ echo " $acdir/$file."
+ echo ""
+ fi
+ done
+fi
+
+rm -rf autom4te.cache
+
+# README and INSTALL are required by automake, but may be deleted by clean
+# up rules. to get automake to work, simply touch these here, they will be
+# regenerated from their corresponding *.in files by ./configure anyway.
+touch README INSTALL
+
+libtoolize --force || exit $?
+intltoolize --force --copy --automake || exit $?
+gtkdocize || exit $?
+
+$ACLOCAL $ACLOCAL_FLAGS || exit $?
+
+autoheader || exit $?
+
+$AUTOMAKE --add-missing || exit $?
+autoconf || exit $?
+cd $ORIGDIR || exit $?
+
+if test -z "$AUTOGEN_SUBDIR_MODE"; then
+ $srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@" || exit $?
+
+ echo
+ echo "Now type 'make' to compile $PROJECT."
+fi
diff --git a/trunk/client/.gitignore b/trunk/client/.gitignore
new file mode 100644
index 00000000..b185be91
--- /dev/null
+++ b/trunk/client/.gitignore
@@ -0,0 +1 @@
+gvfs-fuse-daemon
diff --git a/trunk/client/Makefile.am b/trunk/client/Makefile.am
new file mode 100644
index 00000000..b2aea25d
--- /dev/null
+++ b/trunk/client/Makefile.am
@@ -0,0 +1,82 @@
+NULL =
+
+INCLUDES = -I$(top_srcdir) \
+ -I$(top_srcdir)/client \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \
+ -DGVFS_MODULE_DIR=\"$(libdir)/gvfs/modules\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DDBUS_API_SUBJECT_TO_CHANGE
+
+module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_vfs_.*|g_io_module_load|g_io_module_unload'
+
+## Common to dynamic and static client libs
+
+gvfsclientincludedir=$(includedir)/gvfs-client/gvfs/
+gvfsclientinclude_HEADERS = \
+ gvfsuriutils.h gvfsurimapper.h \
+ $(NULL)
+
+URI_PARSER_SOURCES = \
+ smburi.c \
+ httpuri.c \
+ $(NULL)
+
+vfssources = \
+ gdaemonvfs.c gdaemonvfs.h \
+ gdaemonmount.c gdaemonmount.h \
+ gdaemonvolumemonitor.c gdaemonvolumemonitor.h \
+ gdaemonfile.c gdaemonfile.h \
+ gdaemonfileinputstream.c gdaemonfileinputstream.h \
+ gdaemonfileoutputstream.c gdaemonfileoutputstream.h \
+ gdaemonfileenumerator.c gdaemonfileenumerator.h \
+ gdaemonfilemonitor.c gdaemonfilemonitor.h \
+ gvfsdaemondbus.c gvfsdaemondbus.h \
+ gvfsiconloadable.c gvfsiconloadable.h \
+ gvfsuriutils.c gvfsuriutils.h \
+ gvfsurimapper.c gvfsurimapper.h \
+ $(URI_PARSER_SOURCES) \
+ $(NULL)
+
+vfslibs = \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(DBUS_LIBS) \
+ $(GLIB_LIBS) \
+ $(NULL)
+
+## Dynamic client lib
+
+giomodules_LTLIBRARIES = libgvfsdbus.la
+
+libgvfsdbus_la_LDFLAGS = $(module_flags)
+libgvfsdbus_la_SOURCES = $(vfssources)
+libgvfsdbus_la_LIBADD = $(vfslibs)
+
+noinst_PROGRAMS = test-uri-utils
+
+test_uri_utils_SOURCES = test-uri-utils.c gvfsuriutils.c gvfsuriutils.h
+test_uri_utils_LDADD = $(vfslibs)
+test_uri_utils_CFLAGS = $(INCLUDES)
+
+if USE_FUSE
+
+## FUSE daemon
+
+libexec_PROGRAMS = gvfs-fuse-daemon
+
+gvfs_fuse_daemon_SOURCES = \
+ gvfsfusedaemon.c
+
+gvfs_fuse_daemon_CFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(FUSE_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS-FUSE\" -DG_DISABLE_DEPRECATED \
+ -DDBUS_API_SUBJECT_TO_CHANGE
+
+gvfs_fuse_daemon_LDADD = \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(GLIB_LIBS) $(DBUS_LIBS) $(FUSE_LIBS)
+
+endif
diff --git a/trunk/client/gdaemonfile.c b/trunk/client/gdaemonfile.c
new file mode 100644
index 00000000..9e8eb637
--- /dev/null
+++ b/trunk/client/gdaemonfile.c
@@ -0,0 +1,2805 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "gdaemonfile.h"
+#include "gvfsdaemondbus.h"
+#include "gdaemonmount.h"
+#include <gvfsdaemonprotocol.h>
+#include <gdaemonfileinputstream.h>
+#include <gdaemonfileoutputstream.h>
+#include <gdaemonfilemonitor.h>
+#include <gdaemonfileenumerator.h>
+#include <glib/gi18n-lib.h>
+#include "gdbusutils.h"
+#include "gmountoperationdbus.h"
+#include <gio/gio.h>
+
+static void g_daemon_file_file_iface_init (GFileIface *iface);
+
+struct _GDaemonFile
+{
+ GObject parent_instance;
+
+ GMountSpec *mount_spec;
+ char *path;
+};
+
+static void g_daemon_file_read_async (GFile *file,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data);
+
+G_DEFINE_TYPE_WITH_CODE (GDaemonFile, g_daemon_file, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
+ g_daemon_file_file_iface_init))
+
+static void
+g_daemon_file_finalize (GObject *object)
+{
+ GDaemonFile *daemon_file;
+
+ daemon_file = G_DAEMON_FILE (object);
+
+ g_mount_spec_unref (daemon_file->mount_spec);
+ g_free (daemon_file->path);
+
+ if (G_OBJECT_CLASS (g_daemon_file_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_file_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_file_class_init (GDaemonFileClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_file_finalize;
+}
+
+static void
+g_daemon_file_init (GDaemonFile *daemon_file)
+{
+}
+
+GFile *
+g_daemon_file_new (GMountSpec *mount_spec,
+ const char *path)
+{
+ GDaemonFile *daemon_file;
+
+ daemon_file = g_object_new (G_TYPE_DAEMON_FILE, NULL);
+ daemon_file->mount_spec = g_mount_spec_get_unique_for (mount_spec);
+ daemon_file->path = g_mount_spec_canonicalize_path (path);
+
+ return G_FILE (daemon_file);
+}
+
+static gboolean
+g_daemon_file_is_native (GFile *file)
+{
+ return FALSE;
+}
+
+static gboolean
+g_daemon_file_has_uri_scheme (GFile *file,
+ const char *uri_scheme)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ const char *scheme;
+
+ scheme = _g_daemon_vfs_mountspec_get_uri_scheme (daemon_file->mount_spec);
+ return g_ascii_strcasecmp (scheme, uri_scheme) == 0;
+}
+
+static char *
+g_daemon_file_get_uri_scheme (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ const char *scheme;
+
+ scheme = _g_daemon_vfs_mountspec_get_uri_scheme (daemon_file->mount_spec);
+
+ return g_strdup (scheme);
+}
+
+static char *
+g_daemon_file_get_basename (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ char *last_slash;
+
+ /* This code relies on the path being canonicalized */
+
+ last_slash = strrchr (daemon_file->path, '/');
+ /* If no slash, or only "/" fallback to full path */
+ if (last_slash == NULL ||
+ last_slash[1] == '\0')
+ return g_strdup (daemon_file->path);
+
+ return g_strdup (last_slash + 1);
+}
+
+static char *
+g_daemon_file_get_path (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ GMountInfo *mount_info;
+ const char *rel_path;
+ char *path;
+
+ /* This is a sync i/o call, which is a bit unfortunate, as
+ * this is supposed to be a fast call. However, in almost all
+ * cases this will be cached.
+ */
+
+ mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
+ daemon_file->path,
+ NULL);
+
+ if (mount_info == NULL)
+ return NULL;
+
+ path = NULL;
+
+ if (mount_info->fuse_mountpoint)
+ {
+ rel_path = daemon_file->path +
+ strlen (mount_info->mount_spec->mount_prefix);
+
+ path = g_build_filename (mount_info->fuse_mountpoint, rel_path, NULL);
+ }
+
+ g_mount_info_unref (mount_info);
+
+ return path;
+}
+
+static char *
+g_daemon_file_get_uri (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+
+ return _g_daemon_vfs_get_uri_for_mountspec (daemon_file->mount_spec,
+ daemon_file->path,
+ FALSE);
+}
+
+static char *
+g_daemon_file_get_parse_name (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+
+ return _g_daemon_vfs_get_uri_for_mountspec (daemon_file->mount_spec,
+ daemon_file->path,
+ TRUE);
+}
+
+static GFile *
+new_file_for_new_path (GDaemonFile *daemon_file,
+ const char *new_path)
+{
+ GFile *new_file;
+ GMountSpec *new_spec;
+
+ new_spec = _g_daemon_vfs_get_mount_spec_for_path (daemon_file->mount_spec,
+ daemon_file->path,
+ new_path);
+
+ new_file = g_daemon_file_new (new_spec, new_path);
+ g_mount_spec_unref (new_spec);
+
+ return new_file;
+}
+
+static GFile *
+g_daemon_file_get_parent (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ const char *path;
+ GFile *parent;
+ const char *base;
+ char *parent_path;
+ gsize len;
+
+ path = daemon_file->path;
+ base = strrchr (path, '/');
+ if (base == NULL ||
+ *(base+1) == 0)
+ return NULL;
+
+ while (base > path && *base == '/')
+ base--;
+
+ len = (guint) 1 + base - path;
+
+ parent_path = g_new (gchar, len + 1);
+ g_memmove (parent_path, path, len);
+ parent_path[len] = 0;
+
+ parent = new_file_for_new_path (daemon_file, parent_path);
+ g_free (parent_path);
+
+ return parent;
+}
+
+static GFile *
+g_daemon_file_dup (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+
+ return g_daemon_file_new (daemon_file->mount_spec,
+ daemon_file->path);
+}
+
+static guint
+g_daemon_file_hash (GFile *file)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+
+ return
+ g_str_hash (daemon_file->path) ^
+ GPOINTER_TO_UINT (daemon_file->mount_spec); /* We have unique mount_spec objects so hash directly on it */
+}
+
+static gboolean
+g_daemon_file_equal (GFile *file1,
+ GFile *file2)
+{
+ GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1);
+ GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2);
+
+ return daemon_file1->mount_spec == daemon_file2->mount_spec &&
+ g_str_equal (daemon_file1->path, daemon_file2->path);
+}
+
+
+static const char *
+match_prefix (const char *path, const char *prefix)
+{
+ int prefix_len;
+
+ prefix_len = strlen (prefix);
+ if (strncmp (path, prefix, prefix_len) != 0)
+ return NULL;
+
+ /* Handle the case where prefix is the root, so that
+ * the IS_DIR_SEPRARATOR check below works */
+ if (prefix_len > 0 &&
+ prefix[prefix_len-1] == '/')
+ prefix_len--;
+
+
+ return path + prefix_len;
+}
+
+static gboolean
+g_daemon_file_prefix_matches (GFile *parent,
+ GFile *descendant)
+{
+ GDaemonFile *parent_daemon = G_DAEMON_FILE (parent);
+ GDaemonFile *descendant_daemon = G_DAEMON_FILE (descendant);
+ const char *remainder;
+
+ if (descendant_daemon->mount_spec != parent_daemon->mount_spec)
+ return FALSE;
+
+ remainder = match_prefix (descendant_daemon->path, parent_daemon->path);
+ if (remainder != NULL && *remainder == '/')
+ return TRUE;
+ return FALSE;
+}
+
+static char *
+g_daemon_file_get_relative_path (GFile *parent,
+ GFile *descendant)
+{
+ GDaemonFile *parent_daemon = G_DAEMON_FILE (parent);
+ GDaemonFile *descendant_daemon = G_DAEMON_FILE (descendant);
+ const char *remainder;
+
+ if (descendant_daemon->mount_spec != parent_daemon->mount_spec)
+ return NULL;
+
+ remainder = match_prefix (descendant_daemon->path, parent_daemon->path);
+
+ if (remainder != NULL && *remainder == '/')
+ return g_strdup (remainder + 1);
+ return NULL;
+}
+
+static GFile *
+g_daemon_file_resolve_relative_path (GFile *file,
+ const char *relative_path)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ char *path;
+ GFile *child;
+
+ if (*relative_path == '/')
+ return new_file_for_new_path (daemon_file, relative_path);
+
+ path = g_build_path ("/", daemon_file->path, relative_path, NULL);
+ child = new_file_for_new_path (daemon_file, path);
+ g_free (path);
+
+ return child;
+}
+
+static DBusMessage *
+create_empty_message (GFile *file,
+ const char *op,
+ GMountInfo **mount_info_out,
+ GError **error)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ DBusMessage *message;
+ GMountInfo *mount_info;
+ const char *path;
+
+ mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
+ daemon_file->path,
+ error);
+ if (mount_info == NULL)
+ return NULL;
+
+ if (mount_info_out)
+ *mount_info_out = g_mount_info_ref (mount_info);
+
+ message =
+ dbus_message_new_method_call (mount_info->dbus_id,
+ mount_info->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ op);
+
+ path = g_mount_info_resolve_path (mount_info,
+ daemon_file->path);
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0);
+
+ g_mount_info_unref (mount_info);
+ return message;
+}
+
+static DBusMessage *
+do_sync_path_call (GFile *file,
+ const char *op,
+ GMountInfo **mount_info_out,
+ DBusConnection **connection_out,
+ GCancellable *cancellable,
+ GError **error,
+ int first_arg_type,
+ ...)
+{
+ DBusMessage *message, *reply;
+ va_list var_args;
+ GError *my_error;
+
+ retry:
+
+ message = create_empty_message (file, op, mount_info_out, error);
+ if (!message)
+ return NULL;
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (message,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+
+
+ my_error = NULL;
+ reply = _g_vfs_daemon_call_sync (message,
+ connection_out,
+ NULL, NULL, NULL,
+ cancellable, &my_error);
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ {
+ if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
+ {
+ g_error_free (my_error);
+ goto retry;
+ }
+ g_propagate_error (error, my_error);
+ }
+
+ return reply;
+}
+
+static DBusMessage *
+do_sync_2_path_call (GFile *file1,
+ GFile *file2,
+ const char *op,
+ const char *callback_obj_path,
+ DBusObjectPathMessageFunction callback,
+ gpointer callback_user_data,
+ DBusConnection **connection_out,
+ GCancellable *cancellable,
+ GError **error,
+ int first_arg_type,
+ ...)
+{
+ GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1);
+ GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2);
+ DBusMessage *message, *reply;
+ GMountInfo *mount_info1, *mount_info2;
+ const char *path1, *path2;
+ va_list var_args;
+ GError *my_error;
+
+ retry:
+
+ mount_info1 = _g_daemon_vfs_get_mount_info_sync (daemon_file1->mount_spec,
+ daemon_file1->path,
+ error);
+ if (mount_info1 == NULL)
+ return NULL;
+
+ mount_info2 = NULL;
+ if (daemon_file2)
+ {
+ mount_info2 = _g_daemon_vfs_get_mount_info_sync (daemon_file2->mount_spec,
+ daemon_file2->path,
+ error);
+ if (mount_info2 == NULL)
+ {
+ g_mount_info_unref (mount_info1);
+ return NULL;
+ }
+
+ if (mount_info1 != mount_info2)
+ {
+ g_mount_info_unref (mount_info1);
+ /* For copy this will cause the fallback code to be involved */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported, files on different mounts"));
+ return NULL;
+ }
+ }
+
+ message =
+ dbus_message_new_method_call (mount_info1->dbus_id,
+ mount_info1->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ op);
+
+ path1 = g_mount_info_resolve_path (mount_info1,
+ daemon_file1->path);
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path1, 0);
+
+ if (daemon_file2)
+ {
+ path2 = g_mount_info_resolve_path (mount_info2,
+ daemon_file2->path);
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path2, 0);
+ }
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (message,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+
+ my_error = NULL;
+ reply = _g_vfs_daemon_call_sync (message,
+ connection_out,
+ callback_obj_path,
+ callback,
+ callback_user_data,
+ cancellable, &my_error);
+ dbus_message_unref (message);
+
+ g_mount_info_unref (mount_info1);
+ if (mount_info2)
+ g_mount_info_unref (mount_info2);
+
+ if (reply == NULL)
+ {
+ if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
+ {
+ g_error_free (my_error);
+ goto retry;
+ }
+ g_propagate_error (error, my_error);
+ }
+
+ return reply;
+}
+
+typedef void (*AsyncPathCallCallback) (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data);
+
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ GFile *file;
+ char *op;
+ GCancellable *cancellable;
+ DBusMessage *args;
+ AsyncPathCallCallback callback;
+ gpointer callback_data;
+ GDestroyNotify notify;
+} AsyncPathCall;
+
+static void
+async_path_call_free (AsyncPathCall *data)
+{
+ if (data->notify)
+ data->notify (data->callback_data);
+
+ if (data->result)
+ g_object_unref (data->result);
+ g_object_unref (data->file);
+ g_free (data->op);
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+ if (data->args)
+ dbus_message_unref (data->args);
+ g_free (data);
+}
+
+static void
+async_path_call_done (DBusMessage *reply,
+ DBusConnection *connection,
+ GError *io_error,
+ gpointer _data)
+{
+ AsyncPathCall *data = _data;
+ GSimpleAsyncResult *result;
+
+ if (io_error != NULL)
+ {
+ g_simple_async_result_set_from_error (data->result, io_error);
+ g_simple_async_result_complete (data->result);
+ async_path_call_free (data);
+ }
+ else
+ {
+ result = data->result;
+ g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data);
+ data->result = NULL;
+
+ data->callback (reply, connection,
+ result,
+ data->cancellable,
+ data->callback_data);
+
+ /* Free data here, or later if callback ref:ed the result */
+ g_object_unref (result);
+ }
+}
+
+static void
+do_async_path_call_callback (GMountInfo *mount_info,
+ gpointer _data,
+ GError *error)
+{
+ AsyncPathCall *data = _data;
+ GDaemonFile *daemon_file = G_DAEMON_FILE (data->file);
+ const char *path;
+ DBusMessage *message;
+ DBusMessageIter arg_source, arg_dest;
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (data->result, error);
+ g_simple_async_result_complete (data->result);
+ async_path_call_free (data);
+ return;
+ }
+
+ message =
+ dbus_message_new_method_call (mount_info->dbus_id,
+ mount_info->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ data->op);
+
+ path = g_mount_info_resolve_path (mount_info, daemon_file->path);
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0);
+
+ /* Append more args from data->args */
+
+ if (data->args)
+ {
+ dbus_message_iter_init (data->args, &arg_source);
+ dbus_message_iter_init_append (message, &arg_dest);
+
+ _g_dbus_message_iter_copy (&arg_dest, &arg_source);
+ }
+
+ _g_vfs_daemon_call_async (message,
+ async_path_call_done, data,
+ data->cancellable);
+
+ dbus_message_unref (message);
+}
+
+static void
+do_async_path_call (GFile *file,
+ const char *op,
+ GCancellable *cancellable,
+ GAsyncReadyCallback op_callback,
+ gpointer op_callback_data,
+ AsyncPathCallCallback callback,
+ gpointer callback_data,
+ GDestroyNotify notify,
+ int first_arg_type,
+ ...)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ va_list var_args;
+ AsyncPathCall *data;
+
+ data = g_new0 (AsyncPathCall, 1);
+
+ data->result = g_simple_async_result_new (G_OBJECT (file),
+ op_callback, op_callback_data,
+ NULL);
+
+ data->file = g_object_ref (file);
+ data->op = g_strdup (op);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->callback_data = callback_data;
+ data->notify = notify;
+
+ if (first_arg_type != 0)
+ {
+ data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+ if (data->args == NULL)
+ _g_dbus_oom ();
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (data->args,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+ }
+
+
+ _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec,
+ daemon_file->path,
+ do_async_path_call_callback,
+ data);
+}
+
+
+static GFileEnumerator *
+g_daemon_file_enumerate_children (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+ dbus_uint32_t flags_dbus;
+ char *obj_path;
+ GDaemonFileEnumerator *enumerator;
+ DBusConnection *connection;
+ char *uri;
+
+ enumerator = g_daemon_file_enumerator_new (file);
+ obj_path = g_daemon_file_enumerator_get_object_path (enumerator);
+
+
+ uri = g_file_get_uri (file);
+
+ if (attributes == NULL)
+ attributes = "";
+ flags_dbus = flags;
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_ENUMERATE,
+ NULL, &connection,
+ cancellable, error,
+ DBUS_TYPE_STRING, &obj_path,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_STRING, &uri,
+ 0);
+ g_free (uri);
+ g_free (obj_path);
+
+ if (reply == NULL)
+ goto error;
+
+ dbus_message_unref (reply);
+
+ g_daemon_file_enumerator_set_sync_connection (enumerator, connection);
+
+ return G_FILE_ENUMERATOR (enumerator);
+
+ error:
+ if (reply)
+ dbus_message_unref (reply);
+ g_object_unref (enumerator);
+ return NULL;
+}
+
+static GFileInfo *
+g_daemon_file_query_info (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+ dbus_uint32_t flags_dbus;
+ DBusMessageIter iter;
+ GFileInfo *info;
+ char *uri;
+
+ uri = g_file_get_uri (file);
+
+ if (attributes == NULL)
+ attributes = "";
+ flags_dbus = flags;
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_INFO,
+ NULL, NULL,
+ cancellable, error,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_STRING, &uri,
+ 0);
+
+ g_free (uri);
+
+ if (reply == NULL)
+ return NULL;
+
+ info = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from get_info"));
+ goto out;
+ }
+
+ info = _g_dbus_get_file_info (&iter, error);
+
+ out:
+ dbus_message_unref (reply);
+ return info;
+}
+
+static void
+query_info_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ DBusMessageIter iter;
+ GFileInfo *info;
+ GError *error;
+
+ info = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from query_info"));
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ error = NULL;
+ info = _g_dbus_get_file_info (&iter, &error);
+ if (info == NULL)
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref);
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_query_info_async (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ guint32 dbus_flags;
+ char *uri;
+
+ uri = g_file_get_uri (file);
+
+ dbus_flags = flags;
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_INFO,
+ cancellable,
+ callback, user_data,
+ query_info_async_cb, NULL, NULL,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ DBUS_TYPE_STRING, &uri,
+ 0);
+
+ g_free (uri);
+}
+
+static GFileInfo *
+g_daemon_file_query_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFileInfo *info;
+
+ info = g_simple_async_result_get_op_res_gpointer (simple);
+ if (info)
+ return g_object_ref (info);
+
+ return NULL;
+}
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ gboolean can_seek;
+} GetFDData;
+
+static void
+read_async_get_fd_cb (int fd,
+ gpointer callback_data)
+{
+ GetFDData *data = callback_data;
+ GFileInputStream *stream;
+
+ if (fd == -1)
+ {
+ g_simple_async_result_set_error (data->result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Couldn't get stream file descriptor"));
+ }
+ else
+ {
+ stream = g_daemon_file_input_stream_new (fd, data->can_seek);
+ g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref);
+ }
+
+ g_simple_async_result_complete (data->result);
+
+ g_object_unref (data->result);
+ g_free (data);
+}
+
+static void
+read_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+ GetFDData *get_fd_data;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_INVALID))
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ get_fd_data = g_new0 (GetFDData, 1);
+ get_fd_data->result = g_object_ref (result);
+ get_fd_data->can_seek = can_seek;
+
+ _g_dbus_connection_get_fd_async (connection, fd_id,
+ read_async_get_fd_cb, get_fd_data);
+}
+
+static void
+g_daemon_file_read_async (GFile *file,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ,
+ cancellable,
+ callback, callback_data,
+ read_async_cb, NULL, NULL,
+ 0);
+}
+
+static GFileInputStream *
+g_daemon_file_read_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ gpointer op;
+
+ op = g_simple_async_result_get_op_res_gpointer (simple);
+ if (op)
+ return g_object_ref (op);
+
+ return NULL;
+}
+
+
+static GFileInputStream *
+g_daemon_file_read (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ int fd;
+ DBusMessage *reply;
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ,
+ NULL, &connection,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ return NULL;
+ }
+
+ dbus_message_unref (reply);
+
+ fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
+ if (fd == -1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Didn't get stream file descriptor"));
+ return NULL;
+ }
+
+ return g_daemon_file_input_stream_new (fd, can_seek);
+}
+
+static GFileOutputStream *
+g_daemon_file_append_to (GFile *file,
+ GFileCreateFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ int fd;
+ DBusMessage *reply;
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+ guint16 mode;
+ guint64 initial_offset;
+ dbus_bool_t make_backup;
+ guint32 dbus_flags;
+ char *etag;
+
+ mode = 1;
+ etag = "";
+ make_backup = FALSE;
+ dbus_flags = flags;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ NULL, &connection,
+ cancellable, error,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_UINT64, &initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ return NULL;
+ }
+
+ dbus_message_unref (reply);
+
+ fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
+ if (fd == -1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Didn't get stream file descriptor"));
+ return NULL;
+ }
+
+ return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+}
+
+static GFileOutputStream *
+g_daemon_file_create (GFile *file,
+ GFileCreateFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ int fd;
+ DBusMessage *reply;
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+ guint16 mode;
+ guint64 initial_offset;
+ dbus_bool_t make_backup;
+ char *etag;
+ guint32 dbus_flags;
+
+ mode = 0;
+ etag = "";
+ make_backup = FALSE;
+ dbus_flags = flags;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ NULL, &connection,
+ cancellable, error,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_UINT64, &initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ return NULL;
+ }
+
+ dbus_message_unref (reply);
+
+ fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
+ if (fd == -1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Didn't get stream file descriptor"));
+ return NULL;
+ }
+
+ return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+}
+
+static GFileOutputStream *
+g_daemon_file_replace (GFile *file,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ int fd;
+ DBusMessage *reply;
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+ guint16 mode;
+ guint64 initial_offset;
+ dbus_bool_t dbus_make_backup;
+ guint32 dbus_flags;
+
+ mode = 2;
+ dbus_make_backup = make_backup;
+ dbus_flags = flags;
+
+ if (etag == NULL)
+ etag = "";
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ NULL, &connection,
+ cancellable, error,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &dbus_make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_UINT64, &initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ return NULL;
+ }
+
+ dbus_message_unref (reply);
+
+ fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
+ if (fd == -1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Didn't get stream file descriptor"));
+ return NULL;
+ }
+
+ return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+}
+
+static void
+mount_mountable_location_mounted_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = user_data;
+ GError *error = NULL;
+
+ if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error))
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+
+}
+
+static void
+mount_mountable_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ GMountOperation *mount_operation = callback_data;
+ GMountSpec *mount_spec;
+ char *path;
+ DBusMessageIter iter;
+ GFile *file;
+ dbus_bool_t must_mount_location, is_uri;
+
+ path = NULL;
+
+ dbus_message_iter_init (reply, &iter);
+
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_BOOLEAN, &is_uri,
+ G_DBUS_TYPE_CSTRING, &path,
+ DBUS_TYPE_BOOLEAN, &must_mount_location,
+ 0))
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from call"));
+ g_simple_async_result_complete (result);
+
+ return;
+ }
+
+ if (is_uri)
+ {
+ file = g_file_new_for_uri (path);
+ }
+ else
+ {
+ mount_spec = g_mount_spec_from_dbus (&iter);
+ if (mount_spec == NULL)
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from call"));
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ file = g_daemon_file_new (mount_spec, path);
+ g_mount_spec_unref (mount_spec);
+ }
+
+ g_free (path);
+ g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref);
+
+ if (must_mount_location)
+ {
+ g_file_mount_enclosing_volume (file,
+ 0,
+ mount_operation,
+ cancellable,
+ mount_mountable_location_mounted_cb,
+ g_object_ref (result));
+
+ }
+ else
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_mount_mountable (GFile *file,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GMountSource *mount_source;
+ const char *dbus_id, *obj_path;
+
+ mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
+
+ dbus_id = g_mount_source_get_dbus_id (mount_source);
+ obj_path = g_mount_source_get_obj_path (mount_source);
+
+ if (mount_operation)
+ g_object_ref (mount_operation);
+
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE,
+ cancellable,
+ callback, user_data,
+ mount_mountable_async_cb,
+ mount_operation, mount_operation ? g_object_unref : NULL,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0);
+
+ g_object_unref (mount_source);
+}
+
+static GFile *
+g_daemon_file_mount_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+ GFile *result_file;
+
+ result_file = g_simple_async_result_get_op_res_gpointer (simple);
+ if (result_file)
+ return g_object_ref (result_file);
+
+ return NULL;
+}
+
+static void
+eject_mountable_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_eject_mountable (GFile *file,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ guint32 dbus_flags;
+
+ dbus_flags = flags;
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE,
+ cancellable,
+ callback, user_data,
+ eject_mountable_async_cb,
+ NULL, NULL,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+}
+
+static gboolean
+g_daemon_file_eject_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+unmount_mountable_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_unmount_mountable (GFile *file,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ guint32 dbus_flags;
+
+ dbus_flags = flags;
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE,
+ cancellable,
+ callback, user_data,
+ unmount_mountable_async_cb,
+ NULL, NULL,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+}
+
+static gboolean
+g_daemon_file_unmount_mountable_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+
+typedef struct {
+ GFile *file;
+ GMountOperation *mount_operation;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} MountData;
+
+static void g_daemon_file_mount_enclosing_volume (GFile *location,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+static void
+mount_reply (DBusMessage *reply,
+ GError *error,
+ gpointer user_data)
+{
+ MountData *data = user_data;
+ GSimpleAsyncResult *res;
+
+ if (reply == NULL)
+ {
+ res = g_simple_async_result_new_from_error (G_OBJECT (data->file),
+ data->callback,
+ data->user_data,
+ error);
+ }
+ else
+ {
+ res = g_simple_async_result_new (G_OBJECT (data->file),
+ data->callback,
+ data->user_data,
+ g_daemon_file_mount_enclosing_volume);
+ }
+
+ g_simple_async_result_complete (res);
+
+ g_object_unref (data->file);
+ if (data->mount_operation)
+ g_object_unref (data->mount_operation);
+ g_free (data);
+}
+
+static void
+g_daemon_file_mount_enclosing_volume (GFile *location,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFile *daemon_file;
+ DBusMessage *message;
+ GMountSpec *spec;
+ GMountSource *mount_source;
+ DBusMessageIter iter;
+ MountData *data;
+
+ daemon_file = G_DAEMON_FILE (location);
+
+ message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION);
+
+ spec = g_mount_spec_copy (daemon_file->mount_spec);
+ g_mount_spec_set_mount_prefix (spec, daemon_file->path);
+ dbus_message_iter_init_append (message, &iter);
+ g_mount_spec_to_dbus (&iter, spec);
+ g_mount_spec_unref (spec);
+
+ mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
+ g_mount_source_to_dbus (mount_source, message);
+ g_object_unref (mount_source);
+
+ data = g_new0 (MountData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->file = g_object_ref (location);
+ if (mount_operation)
+ data->mount_operation = g_object_ref (mount_operation);
+
+ /* TODO: Ignoring cancellable here */
+ _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (),
+ message,
+ G_VFS_DBUS_MOUNT_TIMEOUT_MSECS,
+ mount_reply, data);
+
+ dbus_message_unref (message);
+}
+
+static gboolean
+g_daemon_file_mount_enclosing_volume_finish (GFile *location,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Errors handled in generic code */
+ return TRUE;
+}
+
+static GFileInfo *
+g_daemon_file_query_filesystem_info (GFile *file,
+ const char *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ GFileInfo *info;
+
+ if (attributes == NULL)
+ attributes = "";
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO,
+ NULL, NULL,
+ cancellable, error,
+ DBUS_TYPE_STRING, &attributes,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ info = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from get_filesystem_info"));
+ goto out;
+ }
+
+ info = _g_dbus_get_file_info (&iter, error);
+
+ out:
+ dbus_message_unref (reply);
+ return info;
+}
+
+static void
+query_fs_info_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ DBusMessageIter iter;
+ GFileInfo *info;
+ GError *error;
+
+ info = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from query_info"));
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ error = NULL;
+ info = _g_dbus_get_file_info (&iter, &error);
+ if (info == NULL)
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref);
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_query_filesystem_info_async (GFile *file,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO,
+ cancellable,
+ callback, user_data,
+ query_fs_info_async_cb, NULL, NULL,
+ DBUS_TYPE_STRING, &attributes,
+ 0);
+}
+
+static GFileInfo *
+g_daemon_file_query_filesystem_info_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFileInfo *info;
+
+ info = g_simple_async_result_get_op_res_gpointer (simple);
+ if (info)
+ return g_object_ref (info);
+
+ return NULL;
+}
+
+static GMount *
+g_daemon_file_find_enclosing_mount (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ GMountInfo *mount_info;
+ GDaemonMount *mount;
+
+ mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
+ daemon_file->path,
+ error);
+ if (mount_info == NULL)
+ return NULL;
+
+ if (mount_info->user_visible)
+ {
+ /* if we have a daemon volume monitor then return one of it's mounts */
+ mount = g_daemon_volume_monitor_find_mount_by_mount_info (mount_info);
+ if (mount == NULL)
+ {
+ mount = g_daemon_mount_new (mount_info, NULL);
+ }
+ g_mount_info_unref (mount_info);
+
+ if (mount)
+ return G_MOUNT (mount);
+ }
+
+ g_set_error_literal (error, G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ /* translators: this is an error message when there is no user visible "mount" object
+ corresponding to a particular path/uri */
+ _("Could not find enclosing mount"));
+ return NULL;
+}
+
+static GFile *
+g_daemon_file_get_child_for_display_name (GFile *file,
+ const char *display_name,
+ GError **error)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ GMountInfo *mount_info;
+ char *basename;
+ GFile *child;
+
+ mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
+ daemon_file->path,
+ NULL);
+
+
+ if (mount_info && mount_info->prefered_filename_encoding)
+ {
+ basename = g_convert (display_name, -1,
+ mount_info->prefered_filename_encoding,
+ "UTF-8",
+ NULL, NULL,
+ NULL);
+ if (basename == NULL)
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Invalid filename %s"), display_name);
+ return NULL;
+ }
+
+ child = g_file_get_child (file, basename);
+ g_free (basename);
+ }
+ else
+ child = g_file_get_child (file, display_name);
+
+ return child;
+}
+
+static GFile *
+g_daemon_file_set_display_name (GFile *file,
+ const char *display_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFile *daemon_file;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ char *new_path;
+
+ daemon_file = G_DAEMON_FILE (file);
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME,
+ NULL, NULL,
+ cancellable, error,
+ DBUS_TYPE_STRING, &display_name,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ !_g_dbus_message_iter_get_args (&iter, NULL,
+ G_DBUS_TYPE_CSTRING, &new_path,
+ 0))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from query_filesystem_info"));
+ goto out;
+ }
+
+ file = new_file_for_new_path (daemon_file, new_path);
+ g_free (new_path);
+
+ out:
+ dbus_message_unref (reply);
+ return file;
+}
+
+static gboolean
+g_daemon_file_delete (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_DELETE,
+ NULL, NULL,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+static gboolean
+g_daemon_file_trash (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_TRASH,
+ NULL, NULL,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+static gboolean
+g_daemon_file_make_directory (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY,
+ NULL, NULL,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+static gboolean
+g_daemon_file_make_symbolic_link (GFile *file,
+ const char *symlink_value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK,
+ NULL, NULL,
+ cancellable, error,
+ G_DBUS_TYPE_CSTRING, &symlink_value,
+ 0);
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+static GFileAttributeInfoList *
+g_daemon_file_query_settable_attributes (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+ GFileAttributeInfoList *list;
+ DBusMessageIter iter;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES,
+ NULL, NULL,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init (reply, &iter);
+ list = _g_dbus_get_attribute_info_list (&iter, error);
+
+ dbus_message_unref (reply);
+
+ return list;
+}
+
+static GFileAttributeInfoList *
+g_daemon_file_query_writable_namespaces (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *reply;
+ GFileAttributeInfoList *list;
+ DBusMessageIter iter;
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES,
+ NULL, NULL,
+ cancellable, error,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init (reply, &iter);
+ list = _g_dbus_get_attribute_info_list (&iter, error);
+
+ dbus_message_unref (reply);
+
+ return list;
+
+}
+
+static gboolean
+g_daemon_file_set_attribute (GFile *file,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusMessage *message, *reply;
+ DBusMessageIter iter;
+ dbus_uint32_t flags_dbus;
+ GError *my_error;
+
+ retry:
+
+ message = create_empty_message (file, G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE, NULL, error);
+ if (!message)
+ return FALSE;
+
+ dbus_message_iter_init_append (message, &iter);
+
+ flags_dbus = flags;
+ dbus_message_iter_append_basic (&iter,
+ DBUS_TYPE_UINT32,
+ &flags_dbus);
+
+ _g_dbus_append_file_attribute (&iter, attribute, type, value_p);
+
+ my_error = NULL;
+ reply = _g_vfs_daemon_call_sync (message,
+ NULL,
+ NULL, NULL, NULL,
+ cancellable, &my_error);
+
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ {
+ if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
+ {
+ g_error_free (my_error);
+ goto retry;
+ }
+ g_propagate_error (error, my_error);
+ return FALSE;
+ }
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+struct ProgressCallbackData {
+ GFileProgressCallback progress_callback;
+ gpointer progress_callback_data;
+};
+
+static DBusHandlerResult
+progress_callback_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ struct ProgressCallbackData *data = user_data;
+ dbus_uint64_t current_dbus, total_dbus;
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_PROGRESS_INTERFACE,
+ G_VFS_DBUS_PROGRESS_OP_PROGRESS))
+ {
+ if (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_UINT64, &current_dbus,
+ DBUS_TYPE_UINT64, &total_dbus,
+ 0))
+ data->progress_callback (current_dbus, total_dbus, data->progress_callback_data);
+ }
+ else
+ g_warning ("Unknown progress callback message type\n");
+
+ /* TODO: demarshal args and call reall callback */
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static gboolean
+file_transfer (GFile *source,
+ GFile *destination,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data,
+ GError **error)
+{
+ DBusMessage *reply;
+ char *obj_path, *dbus_obj_path;
+ dbus_uint32_t flags_dbus;
+ dbus_bool_t dbus_remove_source;
+ struct ProgressCallbackData data;
+ char *local_path = NULL;
+ gboolean source_is_daemon;
+ gboolean dest_is_daemon;
+ gboolean native_transfer;
+
+ native_transfer = FALSE;
+ source_is_daemon = G_IS_DAEMON_FILE (source);
+ dest_is_daemon = G_IS_DAEMON_FILE (destination);
+
+ if (source_is_daemon && dest_is_daemon)
+ native_transfer = TRUE;
+ else if (dest_is_daemon && !source_is_daemon)
+ local_path = g_file_get_path (source);
+ else if (source_is_daemon && !dest_is_daemon)
+ local_path = g_file_get_path (destination);
+ else
+ {
+ /* Fall back to default copy/move */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Operation not supported");
+ return FALSE;
+ }
+
+ if (!native_transfer && local_path == NULL)
+ {
+ /* This will cause the fallback code to be involved */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported, files on different mounts"));
+ return FALSE;
+
+ }
+
+ if (progress_callback)
+ {
+ obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path);
+ dbus_obj_path = obj_path;
+ }
+ else
+ {
+ obj_path = NULL;
+ /* Can't pass NULL obj path as arg */
+ dbus_obj_path = "/org/gtk/vfs/void";
+ }
+
+ data.progress_callback = progress_callback;
+ data.progress_callback_data = progress_callback_data;
+
+ flags_dbus = flags;
+ dbus_remove_source = remove_source;
+
+ if (native_transfer == TRUE)
+ {
+ const char *method_string;
+
+ if (remove_source == FALSE)
+ method_string = G_VFS_DBUS_MOUNT_OP_COPY;
+ else
+ method_string = G_VFS_DBUS_MOUNT_OP_MOVE;
+
+ reply = do_sync_2_path_call (source, destination,
+ method_string,
+ obj_path, progress_callback_message, &data,
+ NULL, cancellable, error,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
+ 0);
+ }
+ else if (dest_is_daemon == TRUE)
+ {
+ reply = do_sync_2_path_call (destination, NULL,
+ G_VFS_DBUS_MOUNT_OP_PUSH,
+ obj_path, progress_callback_message, &data,
+ NULL, cancellable, error,
+ G_DBUS_TYPE_CSTRING, &local_path,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
+ DBUS_TYPE_BOOLEAN, &dbus_remove_source,
+ 0);
+ }
+ else
+ {
+ reply = do_sync_2_path_call (source, NULL,
+ G_VFS_DBUS_MOUNT_OP_PULL,
+ obj_path, progress_callback_message, &data,
+ NULL, cancellable, error,
+ G_DBUS_TYPE_CSTRING, &local_path,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
+ DBUS_TYPE_BOOLEAN, &dbus_remove_source,
+ 0);
+
+ }
+
+ g_free (local_path);
+ g_free (obj_path);
+
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
+static gboolean
+g_daemon_file_copy (GFile *source,
+ GFile *destination,
+ GFileCopyFlags flags,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data,
+ GError **error)
+{
+ gboolean result;
+
+ result = file_transfer (source,
+ destination,
+ flags,
+ FALSE,
+ cancellable,
+ progress_callback,
+ progress_callback_data,
+ error);
+
+ return result;
+}
+
+static gboolean
+g_daemon_file_move (GFile *source,
+ GFile *destination,
+ GFileCopyFlags flags,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data,
+ GError **error)
+{
+ gboolean result;
+
+ result = file_transfer (source,
+ destination,
+ flags,
+ TRUE,
+ cancellable,
+ progress_callback,
+ progress_callback_data,
+ error);
+
+ return result;
+}
+
+static GFileMonitor*
+g_daemon_file_monitor_dir (GFile* file,
+ GFileMonitorFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GFileMonitor *monitor;
+ char *obj_path;
+ dbus_uint32_t flags_dbus;
+ GMountInfo *mount_info;
+ DBusMessage *reply;
+
+ flags_dbus = flags;
+
+ mount_info = NULL;
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR,
+ &mount_info, NULL,
+ cancellable, error,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ 0);
+
+ if (reply == NULL)
+ {
+ if (mount_info)
+ g_mount_info_unref (mount_info);
+ return NULL;
+ }
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ DBUS_TYPE_INVALID))
+ {
+ g_mount_info_unref (mount_info);
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from monitor_dir"));
+ return NULL;
+ }
+
+ monitor = g_daemon_file_monitor_new (mount_info->dbus_id,
+ obj_path);
+
+ g_mount_info_unref (mount_info);
+ dbus_message_unref (reply);
+
+ return monitor;
+}
+
+static GFileMonitor*
+g_daemon_file_monitor_file (GFile* file,
+ GFileMonitorFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GFileMonitor *monitor;
+ char *obj_path;
+ dbus_uint32_t flags_dbus;
+ GMountInfo *mount_info;
+ DBusMessage *reply;
+
+ flags_dbus = flags;
+
+ mount_info = NULL;
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR,
+ &mount_info, NULL,
+ cancellable, error,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ 0);
+
+ if (reply == NULL)
+ {
+ if (mount_info)
+ g_mount_info_unref (mount_info);
+ return NULL;
+ }
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ DBUS_TYPE_INVALID))
+ {
+ g_mount_info_unref (mount_info);
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from monitor_file"));
+ return NULL;
+ }
+
+ monitor = g_daemon_file_monitor_new (mount_info->dbus_id,
+ obj_path);
+
+ g_mount_info_unref (mount_info);
+ dbus_message_unref (reply);
+
+ return monitor;
+}
+
+typedef struct
+{
+ GSimpleAsyncResult *result;
+ dbus_bool_t can_seek;
+ guint64 initial_offset;
+}
+StreamOpenParams;
+
+static void
+stream_open_cb (gint fd, StreamOpenParams *params)
+{
+ GFileOutputStream *output_stream;
+
+ if (fd == -1)
+ {
+ g_simple_async_result_set_error (params->result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Didn't get stream file descriptor"));
+ goto out;
+ }
+
+ output_stream = g_daemon_file_output_stream_new (fd, params->can_seek, params->initial_offset);
+ g_simple_async_result_set_op_res_gpointer (params->result, output_stream, g_object_unref);
+
+out:
+ g_simple_async_result_complete (params->result);
+ g_object_unref (params->result);
+ g_slice_free (StreamOpenParams, params);
+}
+
+static void
+append_to_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ guint32 fd_id;
+ StreamOpenParams *open_params;
+
+ open_params = g_slice_new0 (StreamOpenParams);
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &open_params->can_seek,
+ DBUS_TYPE_UINT64, &open_params->initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid return value from open"));
+ goto failure;
+ }
+
+ open_params->result = g_object_ref (result);
+ _g_dbus_connection_get_fd_async (connection, fd_id,
+ (GetFdAsyncCallback) stream_open_cb, open_params);
+ return;
+
+failure:
+ g_slice_free (StreamOpenParams, open_params);
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_append_to_async (GFile *file,
+ GFileCreateFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ guint16 mode;
+ dbus_bool_t make_backup;
+ guint32 dbus_flags;
+ char *etag;
+
+ mode = 1;
+ etag = "";
+ make_backup = FALSE;
+ dbus_flags = flags;
+
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ cancellable,
+ callback, user_data,
+ append_to_async_cb, NULL, NULL,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+}
+
+static GFileOutputStream *
+g_daemon_file_append_to_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFileOutputStream *output_stream;
+
+ output_stream = g_simple_async_result_get_op_res_gpointer (simple);
+ if (output_stream)
+ return g_object_ref (output_stream);
+
+ return NULL;
+}
+
+static void
+create_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ guint32 fd_id;
+ StreamOpenParams *open_params;
+
+ open_params = g_slice_new0 (StreamOpenParams);
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &open_params->can_seek,
+ DBUS_TYPE_UINT64, &open_params->initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid return value from open"));
+ goto failure;
+ }
+
+ open_params->result = g_object_ref (result);
+ _g_dbus_connection_get_fd_async (connection, fd_id,
+ (GetFdAsyncCallback) stream_open_cb, open_params);
+ return;
+
+failure:
+ g_slice_free (StreamOpenParams, open_params);
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_create_async (GFile *file,
+ GFileCreateFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ guint16 mode;
+ dbus_bool_t make_backup;
+ char *etag;
+ guint32 dbus_flags;
+
+ mode = 0;
+ etag = "";
+ make_backup = FALSE;
+ dbus_flags = flags;
+
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ cancellable,
+ callback, user_data,
+ create_async_cb, NULL, NULL,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+}
+
+static GFileOutputStream *
+g_daemon_file_create_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFileOutputStream *output_stream;
+
+ output_stream = g_simple_async_result_get_op_res_gpointer (simple);
+ if (output_stream)
+ return g_object_ref (output_stream);
+
+ return NULL;
+}
+
+static void
+enumerate_children_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ GDaemonFileEnumerator *enumerator = callback_data;
+
+ if (reply == NULL || connection == NULL)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid return value from enumerate_children");
+ goto out;
+ }
+
+ g_object_ref (enumerator);
+
+ g_simple_async_result_set_op_res_gpointer (result, enumerator, g_object_unref);
+
+out:
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_enumerate_children_async (GFile *file,
+ const char *attributes,
+ GFileQueryInfoFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ dbus_uint32_t flags_dbus;
+ char *obj_path;
+ GDaemonFileEnumerator *enumerator;
+ char *uri;
+
+ enumerator = g_daemon_file_enumerator_new (file);
+ obj_path = g_daemon_file_enumerator_get_object_path (enumerator);
+
+ uri = g_file_get_uri (file);
+
+ if (attributes == NULL)
+ attributes = "";
+ flags_dbus = flags;
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_ENUMERATE,
+ cancellable,
+ callback, user_data,
+ enumerate_children_async_cb, enumerator, g_object_unref,
+ DBUS_TYPE_STRING, &obj_path,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &flags_dbus,
+ DBUS_TYPE_STRING, &uri,
+ 0);
+ g_free (uri);
+ g_free (obj_path);
+}
+
+static GFileEnumerator *
+g_daemon_file_enumerate_children_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GDaemonFileEnumerator *enumerator;
+
+ enumerator = g_simple_async_result_get_op_res_gpointer (simple);
+ if (enumerator)
+ return g_object_ref (enumerator);
+
+ return NULL;
+}
+
+typedef struct
+{
+ GFile *file;
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+}
+FindEnclosingMountData;
+
+static void
+find_enclosing_mount_cb (GMountInfo *mount_info,
+ gpointer user_data,
+ GError *error)
+{
+ FindEnclosingMountData *data = user_data;
+ GError *my_error = NULL;
+
+ if (data->cancellable && g_cancellable_set_error_if_cancelled (data->cancellable, &my_error))
+ {
+ g_simple_async_result_set_from_error (data->result, my_error);
+ goto out;
+ }
+
+ if (error)
+ {
+ g_simple_async_result_set_from_error (data->result, error);
+ goto out;
+ }
+
+ if (!mount_info)
+ {
+ g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal error: \"%s\"",
+ "No error but no mount info from g_daemon_vfs_get_mount_info_async");
+ goto out;
+ }
+
+ if (mount_info->user_visible)
+ {
+ GDaemonMount *mount;
+
+ /* if we have a daemon volume monitor then return one of it's mounts */
+ mount = g_daemon_volume_monitor_find_mount_by_mount_info (mount_info);
+ if (mount == NULL)
+ mount = g_daemon_mount_new (mount_info, NULL);
+
+ if (mount)
+ g_simple_async_result_set_op_res_gpointer (data->result, mount, g_object_unref);
+ else
+ g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal error: \"%s\"",
+ "Mount info did not yield a mount");
+ }
+
+out:
+ g_simple_async_result_complete (data->result);
+
+ if (my_error)
+ g_error_free (my_error);
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+ g_object_unref (data->file);
+ g_object_unref (data->result);
+ g_free (data);
+}
+
+static void
+g_daemon_file_find_enclosing_mount_async (GFile *file,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFile *daemon_file = G_DAEMON_FILE (file);
+ FindEnclosingMountData *data;
+
+ data = g_new0 (FindEnclosingMountData, 1);
+
+ data->result = g_simple_async_result_new (G_OBJECT (file),
+ callback, user_data,
+ NULL);
+ data->file = g_object_ref (file);
+
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+
+ _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec,
+ daemon_file->path,
+ find_enclosing_mount_cb,
+ data);
+}
+
+static GMount *
+g_daemon_file_find_enclosing_mount_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GMount *mount;
+
+ mount = g_simple_async_result_get_op_res_gpointer (simple);
+ if (mount)
+ return g_object_ref (mount);
+
+ return NULL;
+}
+
+static void
+replace_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ guint32 fd_id;
+ StreamOpenParams *open_params;
+
+ open_params = g_slice_new0 (StreamOpenParams);
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &open_params->can_seek,
+ DBUS_TYPE_UINT64, &open_params->initial_offset,
+ DBUS_TYPE_INVALID))
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid return value from open"));
+ goto failure;
+ }
+
+ open_params->result = g_object_ref (result);
+ _g_dbus_connection_get_fd_async (connection, fd_id,
+ (GetFdAsyncCallback) stream_open_cb, open_params);
+ return;
+
+failure:
+ g_slice_free (StreamOpenParams, open_params);
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_replace_async (GFile *file,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ dbus_bool_t dbus_make_backup = make_backup;
+ guint32 dbus_flags = flags;
+ guint16 mode = 2;
+
+ if (etag == NULL)
+ etag = "";
+
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
+ cancellable,
+ callback, user_data,
+ replace_async_cb, NULL, NULL,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &dbus_make_backup,
+ DBUS_TYPE_UINT32, &dbus_flags,
+ 0);
+}
+
+static GFileOutputStream *
+g_daemon_file_replace_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFileOutputStream *output_stream;
+
+ output_stream = g_simple_async_result_get_op_res_gpointer (simple);
+ if (output_stream)
+ return g_object_ref (output_stream);
+
+ return NULL;
+}
+
+static void
+set_display_name_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ GDaemonFile *daemon_file = callback_data;
+ GFile *file;
+ DBusMessageIter iter;
+ gchar *new_path;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ !_g_dbus_message_iter_get_args (&iter, NULL,
+ G_DBUS_TYPE_CSTRING, &new_path,
+ 0))
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", "Invalid return value from set_display_name");
+ goto out;
+ }
+
+ file = new_file_for_new_path (daemon_file, new_path);
+ g_free (new_path);
+
+ g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref);
+
+out:
+ g_simple_async_result_complete (result);
+}
+
+static void
+g_daemon_file_set_display_name_async (GFile *file,
+ const char *display_name,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_object_ref (file);
+
+ do_async_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME,
+ cancellable,
+ callback, user_data,
+ set_display_name_async_cb, file, g_object_unref,
+ DBUS_TYPE_STRING, &display_name,
+ 0);
+}
+
+static GFile *
+g_daemon_file_set_display_name_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GFile *new_file;
+
+ new_file = g_simple_async_result_get_op_res_gpointer (simple);
+ return new_file;
+}
+
+#if 0
+
+static void
+g_daemon_file_set_attributes_async (GFile *file,
+ GFileInfo *info,
+ GFileQueryInfoFlags flags,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* TODO */
+}
+
+static gboolean
+g_daemon_file_set_attributes_finish (GFile *file,
+ GAsyncResult *result,
+ GFileInfo **info,
+ GError **error)
+{
+ /* TODO */
+}
+
+#endif
+
+static void
+g_daemon_file_file_iface_init (GFileIface *iface)
+{
+ iface->dup = g_daemon_file_dup;
+ iface->hash = g_daemon_file_hash;
+ iface->equal = g_daemon_file_equal;
+ iface->is_native = g_daemon_file_is_native;
+ iface->has_uri_scheme = g_daemon_file_has_uri_scheme;
+ iface->get_uri_scheme = g_daemon_file_get_uri_scheme;
+ iface->get_basename = g_daemon_file_get_basename;
+ iface->get_path = g_daemon_file_get_path;
+ iface->get_uri = g_daemon_file_get_uri;
+ iface->get_parse_name = g_daemon_file_get_parse_name;
+ iface->get_parent = g_daemon_file_get_parent;
+ iface->prefix_matches = g_daemon_file_prefix_matches;
+ iface->get_relative_path = g_daemon_file_get_relative_path;
+ iface->resolve_relative_path = g_daemon_file_resolve_relative_path;
+ iface->get_child_for_display_name = g_daemon_file_get_child_for_display_name;
+ iface->enumerate_children = g_daemon_file_enumerate_children;
+ iface->query_info = g_daemon_file_query_info;
+ iface->query_info_async = g_daemon_file_query_info_async;
+ iface->query_info_finish = g_daemon_file_query_info_finish;
+ iface->find_enclosing_mount = g_daemon_file_find_enclosing_mount;
+ iface->read_fn = g_daemon_file_read;
+ iface->append_to = g_daemon_file_append_to;
+ iface->create = g_daemon_file_create;
+ iface->replace = g_daemon_file_replace;
+ iface->read_async = g_daemon_file_read_async;
+ iface->read_finish = g_daemon_file_read_finish;
+ iface->mount_enclosing_volume = g_daemon_file_mount_enclosing_volume;
+ iface->mount_enclosing_volume_finish = g_daemon_file_mount_enclosing_volume_finish;
+ iface->mount_mountable = g_daemon_file_mount_mountable;
+ iface->mount_mountable_finish = g_daemon_file_mount_mountable_finish;
+ iface->unmount_mountable = g_daemon_file_unmount_mountable;
+ iface->unmount_mountable_finish = g_daemon_file_unmount_mountable_finish;
+ iface->eject_mountable = g_daemon_file_eject_mountable;
+ iface->eject_mountable_finish = g_daemon_file_eject_mountable_finish;
+ iface->query_filesystem_info = g_daemon_file_query_filesystem_info;
+ iface->query_filesystem_info_async = g_daemon_file_query_filesystem_info_async;
+ iface->query_filesystem_info_finish = g_daemon_file_query_filesystem_info_finish;
+ iface->set_display_name = g_daemon_file_set_display_name;
+ iface->delete_file = g_daemon_file_delete;
+ iface->trash = g_daemon_file_trash;
+ iface->make_directory = g_daemon_file_make_directory;
+ iface->copy = g_daemon_file_copy;
+ iface->move = g_daemon_file_move;
+ iface->query_settable_attributes = g_daemon_file_query_settable_attributes;
+ iface->query_writable_namespaces = g_daemon_file_query_writable_namespaces;
+ iface->set_attribute = g_daemon_file_set_attribute;
+ iface->make_symbolic_link = g_daemon_file_make_symbolic_link;
+ iface->monitor_dir = g_daemon_file_monitor_dir;
+ iface->monitor_file = g_daemon_file_monitor_file;
+
+ /* Async operations */
+
+ iface->append_to_async = g_daemon_file_append_to_async;
+ iface->append_to_finish = g_daemon_file_append_to_finish;
+ iface->create_async = g_daemon_file_create_async;
+ iface->create_finish = g_daemon_file_create_finish;
+ iface->enumerate_children_async = g_daemon_file_enumerate_children_async;
+ iface->enumerate_children_finish = g_daemon_file_enumerate_children_finish;
+ iface->find_enclosing_mount_async = g_daemon_file_find_enclosing_mount_async;
+ iface->find_enclosing_mount_finish = g_daemon_file_find_enclosing_mount_finish;
+ iface->replace_async = g_daemon_file_replace_async;
+ iface->replace_finish = g_daemon_file_replace_finish;
+ iface->set_display_name_async = g_daemon_file_set_display_name_async;
+ iface->set_display_name_finish = g_daemon_file_set_display_name_finish;
+#if 0
+ iface->set_attributes_async = g_daemon_file_set_attributes_async;
+ iface->set_attributes_finish = g_daemon_file_set_attributes_finish;
+#endif
+}
diff --git a/trunk/client/gdaemonfile.h b/trunk/client/gdaemonfile.h
new file mode 100644
index 00000000..297066a9
--- /dev/null
+++ b/trunk/client/gdaemonfile.h
@@ -0,0 +1,54 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_FILE_H__
+#define __G_DAEMON_FILE_H__
+
+#include <gio/gio.h>
+#include "gdaemonvfs.h"
+#include "gmountspec.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_FILE (g_daemon_file_get_type ())
+#define G_DAEMON_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE, GDaemonFile))
+#define G_DAEMON_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE, GDaemonFileClass))
+#define G_IS_DAEMON_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE))
+#define G_IS_DAEMON_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE))
+#define G_DAEMON_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE, GDaemonFileClass))
+
+typedef struct _GDaemonFile GDaemonFile;
+typedef struct _GDaemonFileClass GDaemonFileClass;
+
+struct _GDaemonFileClass
+{
+ GObjectClass parent_class;
+};
+
+GType g_daemon_file_get_type (void) G_GNUC_CONST;
+
+GFile * g_daemon_file_new (GMountSpec *mount_spec,
+ const char *path);
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_FILE_H__ */
diff --git a/trunk/client/gdaemonfileenumerator.c b/trunk/client/gdaemonfileenumerator.c
new file mode 100644
index 00000000..56b1488d
--- /dev/null
+++ b/trunk/client/gdaemonfileenumerator.c
@@ -0,0 +1,461 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gdaemonfileenumerator.h>
+#include <gio/gio.h>
+#include <gvfsdaemondbus.h>
+#include <gvfsdaemonprotocol.h>
+
+#define OBJ_PATH_PREFIX "/org/gtk/vfs/client/enumerator/"
+
+/* atomic */
+static volatile gint path_counter = 1;
+
+G_LOCK_DEFINE_STATIC(infos);
+
+struct _GDaemonFileEnumerator
+{
+ GFileEnumerator parent;
+
+ gint id;
+ DBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */
+
+ /* protected by infos lock */
+ GList *infos;
+ gboolean done;
+
+ /* For async ops, also protected by infos lock */
+ int async_requested_files;
+ GCancellable *async_cancel;
+ gulong cancelled_tag;
+ guint timeout_tag;
+ GSimpleAsyncResult *async_res;
+};
+
+G_DEFINE_TYPE (GDaemonFileEnumerator, g_daemon_file_enumerator, G_TYPE_FILE_ENUMERATOR)
+
+static GFileInfo * g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error);
+static void g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator,
+ int num_files,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static GList * g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
+ GAsyncResult *result,
+ GError **error);
+static gboolean g_daemon_file_enumerator_close (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error);
+static void g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static gboolean g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator,
+ GAsyncResult *result,
+ GError **error);
+static DBusHandlerResult g_daemon_file_enumerator_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+static void
+free_info_list (GList *infos)
+{
+ g_list_foreach (infos, (GFunc)g_object_unref, NULL);
+ g_list_free (infos);
+}
+
+static void
+g_daemon_file_enumerator_finalize (GObject *object)
+{
+ GDaemonFileEnumerator *daemon;
+ char *path;
+
+ daemon = G_DAEMON_FILE_ENUMERATOR (object);
+
+ path = g_daemon_file_enumerator_get_object_path (daemon);
+ _g_dbus_unregister_vfs_filter (path);
+ g_free (path);
+
+ free_info_list (daemon->infos);
+
+ if (daemon->sync_connection)
+ dbus_connection_unref (daemon->sync_connection);
+
+ if (G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (object);
+}
+
+
+static void
+g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_file_enumerator_finalize;
+
+ enumerator_class->next_file = g_daemon_file_enumerator_next_file;
+ enumerator_class->next_files_async = g_daemon_file_enumerator_next_files_async;
+ enumerator_class->next_files_finish = g_daemon_file_enumerator_next_files_finish;
+ enumerator_class->close_fn = g_daemon_file_enumerator_close;
+ enumerator_class->close_async = g_daemon_file_enumerator_close_async;
+ enumerator_class->close_finish = g_daemon_file_enumerator_close_finish;
+}
+
+static void
+g_daemon_file_enumerator_init (GDaemonFileEnumerator *daemon)
+{
+ char *path;
+
+ daemon->id = g_atomic_int_exchange_and_add (&path_counter, 1);
+
+ path = g_daemon_file_enumerator_get_object_path (daemon);
+ _g_dbus_register_vfs_filter (path, g_daemon_file_enumerator_dbus_filter,
+ G_OBJECT (daemon));
+ g_free (path);
+}
+
+GDaemonFileEnumerator *
+g_daemon_file_enumerator_new (GFile *file)
+{
+ GDaemonFileEnumerator *daemon;
+
+ daemon = g_object_new (G_TYPE_DAEMON_FILE_ENUMERATOR,
+ "container", file,
+ NULL);
+
+ return daemon;
+}
+
+/* Called with infos lock held */
+static void
+trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
+{
+ GList *rest, *l;
+
+ if (ok)
+ {
+ l = daemon->infos;
+ rest = g_list_nth (l, daemon->async_requested_files);
+ if (rest)
+ {
+ /* Split list */
+ rest->prev->next = NULL;
+ rest->prev = NULL;
+ }
+ daemon->infos = rest;
+
+ g_simple_async_result_set_op_res_gpointer (daemon->async_res,
+ l,
+ (GDestroyNotify)free_info_list);
+ }
+
+ g_simple_async_result_complete_in_idle (daemon->async_res);
+
+ if (daemon->cancelled_tag != 0)
+ g_signal_handler_disconnect (daemon->async_cancel,
+ daemon->cancelled_tag);
+ daemon->async_cancel = 0;
+ daemon->cancelled_tag = 0;
+
+ if (daemon->timeout_tag != 0)
+ g_source_remove (daemon->timeout_tag);
+ daemon->timeout_tag = 0;
+
+ daemon->async_requested_files = 0;
+
+ g_object_unref (daemon->async_res);
+ daemon->async_res = NULL;
+}
+
+static DBusHandlerResult
+g_daemon_file_enumerator_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GDaemonFileEnumerator *enumerator = user_data;
+ const char *member;
+ DBusMessageIter iter, array_iter;
+ GList *infos;
+ GFileInfo *info;
+
+ member = dbus_message_get_member (message);
+
+ if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_DONE) == 0)
+ {
+ G_LOCK (infos);
+ enumerator->done = TRUE;
+ if (enumerator->async_requested_files > 0)
+ trigger_async_done (enumerator, TRUE);
+ G_UNLOCK (infos);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO) == 0)
+ {
+ infos = NULL;
+
+ dbus_message_iter_init (message, &iter);
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY &&
+ dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_STRUCT)
+ {
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ info = _g_dbus_get_file_info (&array_iter, NULL);
+ if (info)
+ g_assert (G_IS_FILE_INFO (info));
+
+ if (info)
+ infos = g_list_prepend (infos, info);
+
+ dbus_message_iter_next (&iter);
+ }
+ }
+
+ infos = g_list_reverse (infos);
+
+ G_LOCK (infos);
+ enumerator->infos = g_list_concat (enumerator->infos, infos);
+ if (enumerator->async_requested_files > 0 &&
+ g_list_length (enumerator->infos) >= enumerator->async_requested_files)
+ trigger_async_done (enumerator, TRUE);
+ G_UNLOCK (infos);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+char *
+g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator)
+{
+ return g_strdup_printf (OBJ_PATH_PREFIX"%d", enumerator->id);
+}
+
+void
+g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator,
+ DBusConnection *connection)
+{
+ enumerator->sync_connection = dbus_connection_ref (connection);
+}
+
+static GFileInfo *
+g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator);
+ GFileInfo *info;
+ gboolean done;
+ int count;
+
+ info = NULL;
+ done = FALSE;
+ count = 0;
+ while (count++ < G_VFS_DBUS_TIMEOUT_MSECS / 100)
+ {
+ G_LOCK (infos);
+ if (daemon->infos)
+ {
+ done = TRUE;
+ info = daemon->infos->data;
+ if (info)
+ g_assert (G_IS_FILE_INFO (info));
+ daemon->infos = g_list_delete_link (daemon->infos, daemon->infos);
+ }
+ else if (daemon->done)
+ done = TRUE;
+ G_UNLOCK (infos);
+
+ if (info)
+ g_assert (G_IS_FILE_INFO (info));
+
+ if (done)
+ break;
+
+ /* We sleep only 100 msecs here, not the full time because we might have
+ * raced with the filter func being called after unlocking
+ * and setting done or ->infos. So, we want to check it again reasonaby soon.
+ */
+ if (daemon->sync_connection != NULL)
+ {
+ /* The initializing call for the enumerator was a sync one, and we
+ have a reference to its private connection. In order to ensure we
+ get the responses sent to that originating connection we pump it
+ here.
+ This should be safe as we're either on the thread that did the call
+ so its our connection, or its the private connection for another
+ thread. If that thread is idle the pumping won't affect anything, and
+ if it is doing something thats ok to, because we don't use filters
+ on the private sync connections so we won't cause any reentrancy
+ (except the file enumerator filter, but that is safe to run in
+ some other thread).
+ */
+ if (!dbus_connection_read_write_dispatch (daemon->sync_connection, 100))
+ break;
+ }
+ else
+ {
+ /* The enumerator was initialized by an async call, so responses will
+ come to the async dbus connection. We can't pump that as that would
+ cause all sort of filters and stuff to run, possibly on the wrong
+ thread. If you want to do async next_files you must create the
+ enumerator asynchrounously.
+ */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Can't do synchronous next_files() on a file enumerator created asynchronously");
+ return NULL;
+ }
+ }
+
+ return info;
+}
+
+static void
+async_cancelled (GCancellable *cancellable,
+ GDaemonFileEnumerator *daemon)
+{
+ g_simple_async_result_set_error (daemon->async_res,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ trigger_async_done (daemon, FALSE);
+}
+
+static gboolean
+async_timeout (gpointer data)
+{
+ GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data);
+ trigger_async_done (daemon, TRUE);
+ return FALSE;
+}
+
+static void
+g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator,
+ int num_files,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator);
+
+ if (daemon->sync_connection != NULL)
+ {
+ /* If the enumerator was created synchronously then the connection used
+ * for return messages will be the private connection for that thread.
+ * We can't rely on it being pumped, so we don't support this.
+ * We could possibly pump it ourselves in this case, but i'm not sure
+ * how much sense this makes, so we don't for now.
+ */
+ g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Can't do asynchronous next_files() on a file enumerator created synchronously");
+ return;
+ }
+
+ G_LOCK (infos);
+ daemon->async_cancel = cancellable;
+ daemon->cancelled_tag = 0;
+ daemon->timeout_tag = 0;
+ daemon->async_requested_files = num_files;
+ daemon->async_res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
+ g_daemon_file_enumerator_next_files_async);
+
+ /* Maybe we already have enough info to fulfill the requeust already */
+ if (daemon->done ||
+ g_list_length (daemon->infos) >= daemon->async_requested_files)
+ trigger_async_done (daemon, TRUE);
+ else
+ {
+ if (cancellable)
+ daemon->cancelled_tag = g_signal_connect (cancellable, "cancelled", (GCallback)async_cancelled, daemon);
+ daemon->timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS,
+ async_timeout, daemon);
+ }
+
+ G_UNLOCK (infos);
+}
+
+static GList *
+g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
+ GAsyncResult *result,
+ GError **error)
+{
+ GList *l;
+
+ l = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ /* We want the caller to own this, and not the result, so clear the result data */
+ g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
+ NULL, NULL);
+
+ return l;
+}
+
+static gboolean
+g_daemon_file_enumerator_close (GFileEnumerator *enumerator,
+ GCancellable *cancellable,
+ GError **error)
+{
+ /*GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); */
+
+ return TRUE;
+}
+
+
+/* We want an explicitly async version of close (doing nothing) to avoid
+ the default thread-using version. */
+static void
+g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data,
+ g_daemon_file_enumerator_close_async);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+}
+
+static gboolean
+g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
diff --git a/trunk/client/gdaemonfileenumerator.h b/trunk/client/gdaemonfileenumerator.h
new file mode 100644
index 00000000..25f5195a
--- /dev/null
+++ b/trunk/client/gdaemonfileenumerator.h
@@ -0,0 +1,57 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_FILE_ENUMERATOR_H__
+#define __G_DAEMON_FILE_ENUMERATOR_H__
+
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_FILE_ENUMERATOR (g_daemon_file_enumerator_get_type ())
+#define G_DAEMON_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumerator))
+#define G_DAEMON_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumeratorClass))
+#define G_IS_DAEMON_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_ENUMERATOR))
+#define G_IS_DAEMON_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_ENUMERATOR))
+#define G_DAEMON_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_ENUMERATOR, GDaemonFileEnumeratorClass))
+
+typedef struct _GDaemonFileEnumerator GDaemonFileEnumerator;
+typedef struct _GDaemonFileEnumeratorClass GDaemonFileEnumeratorClass;
+typedef struct _GDaemonFileEnumeratorPrivate GDaemonFileEnumeratorPrivate;
+
+struct _GDaemonFileEnumeratorClass
+{
+ GFileEnumeratorClass parent_class;
+};
+
+GType g_daemon_file_enumerator_get_type (void) G_GNUC_CONST;
+
+GDaemonFileEnumerator *g_daemon_file_enumerator_new (GFile *file);
+char * g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator);
+void g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator,
+ DBusConnection *connection);
+
+
+G_END_DECLS
+
+#endif /* __G_FILE_DAEMON_FILE_ENUMERATOR_H__ */
diff --git a/trunk/client/gdaemonfileinputstream.c b/trunk/client/gdaemonfileinputstream.c
new file mode 100644
index 00000000..69f70c62
--- /dev/null
+++ b/trunk/client/gdaemonfileinputstream.c
@@ -0,0 +1,2118 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include "gdaemonfileinputstream.h"
+#include "gvfsdaemondbus.h"
+#include <gvfsdaemonprotocol.h>
+#include <gvfsfileinfo.h>
+
+#define MAX_READ_SIZE (4*1024*1024)
+
+typedef enum {
+ INPUT_STATE_IN_REPLY_HEADER,
+ INPUT_STATE_IN_BLOCK
+} InputState;
+
+typedef enum {
+ STATE_OP_DONE,
+ STATE_OP_READ,
+ STATE_OP_WRITE,
+ STATE_OP_SKIP
+} StateOp;
+
+typedef enum {
+ READ_STATE_INIT = 0,
+ READ_STATE_WROTE_COMMAND,
+ READ_STATE_HANDLE_INPUT,
+ READ_STATE_HANDLE_INPUT_BLOCK,
+ READ_STATE_SKIP_BLOCK,
+ READ_STATE_HANDLE_HEADER,
+ READ_STATE_READ_BLOCK
+} ReadState;
+
+typedef struct {
+ ReadState state;
+
+ /* Input */
+ char *buffer;
+ gsize buffer_size;
+ /* Output */
+ gssize ret_val;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} ReadOperation;
+
+typedef enum {
+ SEEK_STATE_INIT = 0,
+ SEEK_STATE_WROTE_REQUEST,
+ SEEK_STATE_HANDLE_INPUT,
+ SEEK_STATE_HANDLE_INPUT_BLOCK,
+ SEEK_STATE_SKIP_BLOCK,
+ SEEK_STATE_HANDLE_HEADER
+} SeekState;
+
+typedef struct {
+ SeekState state;
+
+ /* Input */
+ goffset offset;
+ GSeekType seek_type;
+ /* Output */
+ gboolean ret_val;
+ GError *ret_error;
+ goffset ret_offset;
+
+ gboolean sent_cancel;
+ gboolean sent_seek;
+
+ guint32 seq_nr;
+} SeekOperation;
+
+typedef enum {
+ CLOSE_STATE_INIT = 0,
+ CLOSE_STATE_WROTE_REQUEST,
+ CLOSE_STATE_HANDLE_INPUT,
+ CLOSE_STATE_HANDLE_INPUT_BLOCK,
+ CLOSE_STATE_SKIP_BLOCK,
+ CLOSE_STATE_HANDLE_HEADER
+} CloseState;
+
+typedef struct {
+ CloseState state;
+
+ /* Input */
+
+ /* Output */
+ gboolean ret_val;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} CloseOperation;
+
+typedef enum {
+ QUERY_STATE_INIT = 0,
+ QUERY_STATE_WROTE_REQUEST,
+ QUERY_STATE_HANDLE_INPUT,
+ QUERY_STATE_HANDLE_INPUT_BLOCK,
+ QUERY_STATE_HANDLE_HEADER,
+ QUERY_STATE_READ_BLOCK,
+ QUERY_STATE_SKIP_BLOCK
+} QueryState;
+
+typedef struct {
+ QueryState state;
+
+ /* Input */
+ char *attributes;
+
+ /* Output */
+ GFileInfo *info;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} QueryOperation;
+
+typedef struct {
+ gboolean cancelled;
+
+ char *io_buffer;
+ gsize io_size;
+ gsize io_res;
+ /* The operation always succeeds, or gets cancelled.
+ If we get an error doing the i/o that is considered fatal */
+ gboolean io_allow_cancel;
+ gboolean io_cancelled;
+} IOOperationData;
+
+typedef struct {
+ char *data;
+ gsize len;
+ int seek_generation;
+} PreRead;
+
+typedef StateOp (*state_machine_iterator) (GDaemonFileInputStream *file,
+ IOOperationData *io_op,
+ gpointer data);
+
+struct _GDaemonFileInputStream {
+ GFileInputStream parent;
+
+ GOutputStream *command_stream;
+ GInputStream *data_stream;
+ guint can_seek : 1;
+
+ int seek_generation;
+ guint32 seq_nr;
+ goffset current_offset;
+
+ GList *pre_reads;
+
+ InputState input_state;
+ gsize input_block_size;
+ int input_block_seek_generation;
+ GString *input_buffer;
+
+ GString *output_buffer;
+};
+
+static gssize g_daemon_file_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gssize g_daemon_file_input_stream_skip (GInputStream *stream,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_daemon_file_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static GFileInfo *g_daemon_file_input_stream_query_info (GFileInputStream *stream,
+ const char *attributes,
+ GCancellable *cancellable,
+ GError **error);
+static goffset g_daemon_file_input_stream_tell (GFileInputStream *stream);
+static gboolean g_daemon_file_input_stream_can_seek (GFileInputStream *stream);
+static gboolean g_daemon_file_input_stream_seek (GFileInputStream *stream,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error);
+static void g_daemon_file_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_daemon_file_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_daemon_file_input_stream_skip_async (GInputStream *stream,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_daemon_file_input_stream_skip_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_daemon_file_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean g_daemon_file_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_daemon_file_input_stream_query_info_async (GFileInputStream *stream,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static GFileInfo *g_daemon_file_input_stream_query_info_finish (GFileInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+
+
+G_DEFINE_TYPE (GDaemonFileInputStream, g_daemon_file_input_stream,
+ G_TYPE_FILE_INPUT_STREAM)
+
+static void
+pre_read_free (PreRead *pre)
+{
+ g_free (pre->data);
+ g_free (pre);
+}
+
+static void
+g_string_remove_in_front (GString *string,
+ gsize bytes)
+{
+ memmove (string->str,
+ string->str + bytes,
+ string->len - bytes);
+ g_string_truncate (string,
+ string->len - bytes);
+}
+
+static void
+g_daemon_file_input_stream_finalize (GObject *object)
+{
+ GDaemonFileInputStream *file;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (object);
+
+ if (file->command_stream)
+ g_object_unref (file->command_stream);
+ if (file->data_stream)
+ g_object_unref (file->data_stream);
+
+ while (file->pre_reads)
+ {
+ PreRead *pre = file->pre_reads->data;
+ file->pre_reads = g_list_delete_link (file->pre_reads,
+ file->pre_reads);
+ pre_read_free (pre);
+ }
+
+ g_string_free (file->input_buffer, TRUE);
+ g_string_free (file->output_buffer, TRUE);
+
+ if (G_OBJECT_CLASS (g_daemon_file_input_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_file_input_stream_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_file_input_stream_class_init (GDaemonFileInputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+ GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_file_input_stream_finalize;
+
+ stream_class->read_fn = g_daemon_file_input_stream_read;
+ if (0) stream_class->skip = g_daemon_file_input_stream_skip;
+ stream_class->close_fn = g_daemon_file_input_stream_close;
+
+ stream_class->read_async = g_daemon_file_input_stream_read_async;
+ stream_class->read_finish = g_daemon_file_input_stream_read_finish;
+ if (0)
+ {
+ stream_class->skip_async = g_daemon_file_input_stream_skip_async;
+ stream_class->skip_finish = g_daemon_file_input_stream_skip_finish;
+ }
+ stream_class->close_async = g_daemon_file_input_stream_close_async;
+ stream_class->close_finish = g_daemon_file_input_stream_close_finish;
+
+ file_stream_class->tell = g_daemon_file_input_stream_tell;
+ file_stream_class->can_seek = g_daemon_file_input_stream_can_seek;
+ file_stream_class->seek = g_daemon_file_input_stream_seek;
+ file_stream_class->query_info = g_daemon_file_input_stream_query_info;
+ file_stream_class->query_info_async = g_daemon_file_input_stream_query_info_async;
+ file_stream_class->query_info_finish = g_daemon_file_input_stream_query_info_finish;
+
+}
+
+static void
+g_daemon_file_input_stream_init (GDaemonFileInputStream *info)
+{
+ info->output_buffer = g_string_new ("");
+ info->input_buffer = g_string_new ("");
+ info->seq_nr = 1;
+}
+
+GFileInputStream *
+g_daemon_file_input_stream_new (int fd,
+ gboolean can_seek)
+{
+ GDaemonFileInputStream *stream;
+
+ stream = g_object_new (G_TYPE_DAEMON_FILE_INPUT_STREAM, NULL);
+
+ stream->command_stream = g_unix_output_stream_new (fd, FALSE);
+ stream->data_stream = g_unix_input_stream_new (fd, TRUE);
+ stream->can_seek = can_seek;
+
+ return G_FILE_INPUT_STREAM (stream);
+}
+
+static gboolean
+error_is_cancel (GError *error)
+{
+ return error != NULL &&
+ error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_CANCELLED;
+}
+
+static void
+append_request (GDaemonFileInputStream *stream, guint32 command,
+ guint32 arg1, guint32 arg2, guint32 data_len,
+ guint32 *seq_nr)
+{
+ GVfsDaemonSocketProtocolRequest cmd;
+
+ g_assert (sizeof (cmd) == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE);
+
+ if (seq_nr)
+ *seq_nr = stream->seq_nr;
+
+ cmd.command = g_htonl (command);
+ cmd.seq_nr = g_htonl (stream->seq_nr);
+ cmd.arg1 = g_htonl (arg1);
+ cmd.arg2 = g_htonl (arg2);
+ cmd.data_len = g_htonl (data_len);
+
+ stream->seq_nr++;
+
+ g_string_append_len (stream->output_buffer,
+ (char *)&cmd, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE);
+}
+
+static gsize
+get_reply_header_missing_bytes (GString *buffer)
+{
+ GVfsDaemonSocketProtocolReply *reply;
+ guint32 type;
+ guint32 arg2;
+
+ if (buffer->len < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE)
+ return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE - buffer->len;
+
+ reply = (GVfsDaemonSocketProtocolReply *)buffer->str;
+
+ type = g_ntohl (reply->type);
+ arg2 = g_ntohl (reply->arg2);
+
+ if (type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR ||
+ type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO)
+ return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + arg2 - buffer->len;
+ return 0;
+}
+
+static char *
+decode_reply (GString *buffer, GVfsDaemonSocketProtocolReply *reply_out)
+{
+ GVfsDaemonSocketProtocolReply *reply;
+ reply = (GVfsDaemonSocketProtocolReply *)buffer->str;
+ reply_out->type = g_ntohl (reply->type);
+ reply_out->seq_nr = g_ntohl (reply->seq_nr);
+ reply_out->arg1 = g_ntohl (reply->arg1);
+ reply_out->arg2 = g_ntohl (reply->arg2);
+
+ return buffer->str + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE;
+}
+
+static void
+decode_error (GVfsDaemonSocketProtocolReply *reply, char *data, GError **error)
+{
+ g_set_error_literal (error,
+ g_quark_from_string (data),
+ reply->arg1,
+ data + strlen (data) + 1);
+}
+
+
+static gboolean
+run_sync_state_machine (GDaemonFileInputStream *file,
+ state_machine_iterator iterator,
+ gpointer data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gssize res;
+ StateOp io_op;
+ IOOperationData io_data;
+ GError *io_error;
+
+ memset (&io_data, 0, sizeof (io_data));
+
+ while (TRUE)
+ {
+ if (cancellable)
+ io_data.cancelled = g_cancellable_is_cancelled (cancellable);
+
+ io_op = iterator (file, &io_data, data);
+
+ if (io_op == STATE_OP_DONE)
+ return TRUE;
+
+ io_error = NULL;
+ if (io_op == STATE_OP_READ)
+ {
+ res = g_input_stream_read (file->data_stream,
+ io_data.io_buffer, io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else if (io_op == STATE_OP_SKIP)
+ {
+ res = g_input_stream_skip (file->data_stream,
+ io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else if (io_op == STATE_OP_WRITE)
+ {
+ res = g_output_stream_write (file->command_stream,
+ io_data.io_buffer, io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else
+ {
+ res = 0;
+ g_assert_not_reached ();
+ }
+
+ if (res == -1)
+ {
+ if (error_is_cancel (io_error))
+ {
+ io_data.io_res = 0;
+ io_data.io_cancelled = TRUE;
+ g_error_free (io_error);
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), io_error->message);
+ g_error_free (io_error);
+ return FALSE;
+ }
+ }
+ else if (res == 0 && io_data.io_size != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), _("End of stream"));
+ return FALSE;
+ }
+ else
+ {
+ io_data.io_res = res;
+ io_data.io_cancelled = FALSE;
+ }
+ }
+}
+
+/* read cycle:
+
+ if we know of a (partially read) matching outstanding block, read from it
+ create packet, append to outgoing
+ flush outgoing
+ start processing input, looking for a data block with same seek gen,
+ or an error with same seq nr
+ on cancel, send cancel command and go back to loop
+ */
+
+static StateOp
+iterate_read_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, ReadOperation *op)
+{
+ gsize len;
+ PreRead *pre;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case READ_STATE_INIT:
+
+ while (file->pre_reads)
+ {
+ pre = file->pre_reads->data;
+ if (file->seek_generation != pre->seek_generation)
+ {
+ file->pre_reads = g_list_delete_link (file->pre_reads,
+ file->pre_reads);
+ pre_read_free (pre);
+ }
+ else
+ {
+ len = MIN (op->buffer_size, pre->len);
+ memcpy (op->buffer, pre->data, len);
+ op->ret_val = len;
+ op->ret_error = NULL;
+
+ if (len < pre->len)
+ {
+ memmove (pre->data, pre->data + len, pre->len - len);
+ pre->len -= len;
+ }
+ else
+ {
+ file->pre_reads = g_list_delete_link (file->pre_reads,
+ file->pre_reads);
+ pre_read_free (pre);
+ }
+
+ return STATE_OP_DONE;
+ }
+ }
+
+
+ /* If we're already reading some data, but we didn't read all, just use that
+ and don't even send a request */
+ if (file->input_state == INPUT_STATE_IN_BLOCK &&
+ file->seek_generation == file->input_block_seek_generation)
+ {
+ op->state = READ_STATE_READ_BLOCK;
+ io_op->io_buffer = op->buffer;
+ io_op->io_size = MIN (op->buffer_size, file->input_block_size);
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before we sent request */
+ return STATE_OP_READ;
+ }
+
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ,
+ op->buffer_size, 0, 0, &op->seq_nr);
+ op->state = READ_STATE_WROTE_COMMAND;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case READ_STATE_WROTE_COMMAND:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = -1;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = READ_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case READ_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = READ_STATE_WROTE_COMMAND;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (file->input_state == INPUT_STATE_IN_BLOCK)
+ {
+ op->state = READ_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER)
+ {
+ op->state = READ_STATE_HANDLE_HEADER;
+ break;
+ }
+ g_assert_not_reached ();
+ break;
+
+ /* No op */
+ case READ_STATE_HANDLE_INPUT_BLOCK:
+ g_assert (file->input_state == INPUT_STATE_IN_BLOCK);
+
+ if (file->seek_generation ==
+ file->input_block_seek_generation)
+ {
+ op->state = READ_STATE_READ_BLOCK;
+ io_op->io_buffer = op->buffer;
+ io_op->io_size = MIN (op->buffer_size, file->input_block_size);
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_READ;
+ }
+ else
+ {
+ op->state = READ_STATE_SKIP_BLOCK;
+ io_op->io_buffer = NULL;
+ io_op->io_size = file->input_block_size;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_SKIP;
+ }
+ break;
+
+ /* Read block data */
+ case READ_STATE_SKIP_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ op->state = READ_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+
+ op->state = READ_STATE_HANDLE_INPUT;
+ break;
+
+ /* read header data, (or manual io_len/res = 0) */
+ case READ_STATE_HANDLE_HEADER:
+ if (io_op->io_cancelled)
+ {
+ op->state = READ_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = file->input_buffer->len == 0 && !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = -1;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA)
+ {
+ g_string_truncate (file->input_buffer, 0);
+ file->input_state = INPUT_STATE_IN_BLOCK;
+ file->input_block_size = reply.arg1;
+ file->input_block_seek_generation = reply.arg2;
+ op->state = READ_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = READ_STATE_HANDLE_HEADER;
+ break;
+
+ /* Read block data */
+ case READ_STATE_READ_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = -1;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+ }
+
+ op->ret_val = io_op->io_res;
+ op->ret_error = NULL;
+ return STATE_OP_DONE;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+
+ }
+}
+
+static gssize
+g_daemon_file_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileInputStream *file;
+ ReadOperation op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ /* Limit for sanity and to avoid 32bit overflow */
+ if (count > MAX_READ_SIZE)
+ count = MAX_READ_SIZE;
+
+ memset (&op, 0, sizeof (op));
+ op.state = READ_STATE_INIT;
+ op.buffer = buffer;
+ op.buffer_size = count;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_read_state_machine,
+ &op, cancellable, error))
+ return -1; /* IO Error */
+
+ if (op.ret_val == -1)
+ g_propagate_error (error, op.ret_error);
+ else
+ file->current_offset += op.ret_val;
+
+ return op.ret_val;
+}
+
+static gssize
+g_daemon_file_input_stream_skip (GInputStream *stream,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+#if 0
+ GDaemonFileInputStream *file;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+#endif
+ /* TODO: implement skip */
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static StateOp
+iterate_close_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, CloseOperation *op)
+{
+ gsize len;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case CLOSE_STATE_INIT:
+
+ /* Clear any pre-read data blocks */
+ while (file->pre_reads)
+ {
+ PreRead *pre = file->pre_reads->data;
+ file->pre_reads = g_list_delete_link (file->pre_reads,
+ file->pre_reads);
+ pre_read_free (pre);
+ }
+
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE,
+ 0, 0, 0, &op->seq_nr);
+ op->state = CLOSE_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case CLOSE_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = FALSE;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case CLOSE_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = CLOSE_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (file->input_state == INPUT_STATE_IN_BLOCK)
+ {
+ op->state = CLOSE_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER)
+ {
+ op->state = CLOSE_STATE_HANDLE_HEADER;
+ break;
+ }
+ g_assert_not_reached ();
+ break;
+
+ /* No op */
+ case CLOSE_STATE_HANDLE_INPUT_BLOCK:
+ g_assert (file->input_state == INPUT_STATE_IN_BLOCK);
+
+ op->state = CLOSE_STATE_SKIP_BLOCK;
+ io_op->io_buffer = NULL;
+ io_op->io_size = file->input_block_size;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_SKIP;
+
+ /* Read block data */
+ case CLOSE_STATE_SKIP_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+
+ /* read header data, (or manual io_len/res = 0) */
+ case CLOSE_STATE_HANDLE_HEADER:
+ if (io_op->io_cancelled)
+ {
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = file->input_buffer->len == 0 && !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = FALSE;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA)
+ {
+ g_string_truncate (file->input_buffer, 0);
+ file->input_state = INPUT_STATE_IN_BLOCK;
+ file->input_block_size = reply.arg1;
+ file->input_block_seek_generation = reply.arg2;
+ op->state = CLOSE_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED)
+ {
+ op->ret_val = TRUE;
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = CLOSE_STATE_HANDLE_HEADER;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+
+static gboolean
+g_daemon_file_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileInputStream *file;
+ CloseOperation op;
+ gboolean res;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ /* We need to do a full roundtrip to guarantee that the writes have
+ reached the disk. */
+
+ memset (&op, 0, sizeof (op));
+ op.state = CLOSE_STATE_INIT;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_close_state_machine,
+ &op, cancellable, error))
+ res = FALSE;
+ else
+ {
+ if (!op.ret_val)
+ g_propagate_error (error, op.ret_error);
+ res = op.ret_val;
+ }
+
+ /* Return the first error, but close all streams */
+ if (res)
+ res = g_output_stream_close (file->command_stream, cancellable, error);
+ else
+ g_output_stream_close (file->command_stream, cancellable, NULL);
+
+ if (res)
+ res = g_input_stream_close (file->data_stream, cancellable, error);
+ else
+ g_input_stream_close (file->data_stream, cancellable, NULL);
+
+ return res;
+}
+
+static goffset
+g_daemon_file_input_stream_tell (GFileInputStream *stream)
+{
+ GDaemonFileInputStream *file;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ return file->current_offset;
+}
+
+static gboolean
+g_daemon_file_input_stream_can_seek (GFileInputStream *stream)
+{
+ GDaemonFileInputStream *file;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ return file->can_seek;
+}
+
+static StateOp
+iterate_seek_state_machine (GDaemonFileInputStream *file, IOOperationData *io_op, SeekOperation *op)
+{
+ gsize len;
+ guint32 request;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case SEEK_STATE_INIT:
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET;
+ if (op->seek_type == G_SEEK_CUR)
+ op->offset = file->current_offset + op->offset;
+ else if (op->seek_type == G_SEEK_END)
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END;
+ append_request (file, request,
+ op->offset & 0xffffffff,
+ op->offset >> 32,
+ 0,
+ &op->seq_nr);
+ op->state = SEEK_STATE_WROTE_REQUEST;
+ op->sent_seek = FALSE;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case SEEK_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = -1;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ /* We weren't cancelled before first byte sent, so now we will send
+ * the seek request. Increase the seek generation now. */
+ if (!op->sent_seek)
+ file->seek_generation++;
+ op->sent_seek = TRUE;
+
+ /* Clear any pre-read data blocks */
+ while (file->pre_reads)
+ {
+ PreRead *pre = file->pre_reads->data;
+ file->pre_reads = g_list_delete_link (file->pre_reads,
+ file->pre_reads);
+ pre_read_free (pre);
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case SEEK_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = SEEK_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (file->input_state == INPUT_STATE_IN_BLOCK)
+ {
+ op->state = SEEK_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER)
+ {
+ op->state = SEEK_STATE_HANDLE_HEADER;
+ break;
+ }
+ g_assert_not_reached ();
+ break;
+
+ /* No op */
+ case SEEK_STATE_HANDLE_INPUT_BLOCK:
+ g_assert (file->input_state == INPUT_STATE_IN_BLOCK);
+
+ op->state = SEEK_STATE_SKIP_BLOCK;
+ /* Reuse client buffer for skipping */
+ io_op->io_buffer = NULL;
+ io_op->io_size = file->input_block_size;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_SKIP;
+
+ /* Read block data */
+ case SEEK_STATE_SKIP_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+
+ /* read header data, (or manual io_len/res = 0) */
+ case SEEK_STATE_HANDLE_HEADER:
+ if (io_op->io_cancelled)
+ {
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = file->input_buffer->len == 0 && !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = FALSE;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA)
+ {
+ g_string_truncate (file->input_buffer, 0);
+ file->input_state = INPUT_STATE_IN_BLOCK;
+ file->input_block_size = reply.arg1;
+ file->input_block_seek_generation = reply.arg2;
+ op->state = SEEK_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS)
+ {
+ op->ret_val = TRUE;
+ op->ret_offset = ((goffset)reply.arg2) << 32 | (goffset)reply.arg1;
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = SEEK_STATE_HANDLE_HEADER;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+static gboolean
+g_daemon_file_input_stream_seek (GFileInputStream *stream,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileInputStream *file;
+ SeekOperation op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ if (!file->can_seek)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Seek not supported on stream"));
+ return FALSE;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ memset (&op, 0, sizeof (op));
+ op.state = SEEK_STATE_INIT;
+ op.offset = offset;
+ op.seek_type = type;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_seek_state_machine,
+ &op, cancellable, error))
+ return FALSE; /* IO Error */
+
+ if (!op.ret_val)
+ g_propagate_error (error, op.ret_error);
+ else
+ file->current_offset = op.ret_offset;
+
+ return op.ret_val;
+}
+
+static StateOp
+iterate_query_state_machine (GDaemonFileInputStream *file,
+ IOOperationData *io_op,
+ QueryOperation *op)
+{
+ gsize len;
+ guint32 request;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case QUERY_STATE_INIT:
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_QUERY_INFO;
+ append_request (file, request,
+ 0,
+ 0,
+ strlen (op->attributes),
+ &op->seq_nr);
+ g_string_append (file->output_buffer,
+ op->attributes);
+
+ op->state = QUERY_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case QUERY_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->info = NULL;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case QUERY_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = QUERY_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (file->input_state == INPUT_STATE_IN_BLOCK)
+ {
+ op->state = QUERY_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (file->input_state == INPUT_STATE_IN_REPLY_HEADER)
+ {
+ op->state = QUERY_STATE_HANDLE_HEADER;
+ break;
+ }
+ g_assert_not_reached ();
+ break;
+
+ /* No op */
+ case QUERY_STATE_HANDLE_INPUT_BLOCK:
+ g_assert (file->input_state == INPUT_STATE_IN_BLOCK);
+
+ if (file->input_block_size == 0)
+ {
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (file->seek_generation ==
+ file->input_block_seek_generation)
+ {
+ op->state = QUERY_STATE_READ_BLOCK;
+ io_op->io_buffer = g_malloc (file->input_block_size);
+ io_op->io_size = file->input_block_size;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_READ;
+ }
+ else
+ {
+ op->state = QUERY_STATE_SKIP_BLOCK;
+ io_op->io_buffer = NULL;
+ io_op->io_size = file->input_block_size;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_SKIP;
+ }
+ break;
+
+ /* Read block data */
+ case QUERY_STATE_SKIP_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+
+ /* Read block data */
+ case QUERY_STATE_READ_BLOCK:
+ if (io_op->io_cancelled)
+ {
+ g_free (io_op->io_buffer);
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ PreRead *pre;
+
+ g_assert (io_op->io_res <= file->input_block_size);
+ file->input_block_size -= io_op->io_res;
+ if (file->input_block_size == 0)
+ file->input_state = INPUT_STATE_IN_REPLY_HEADER;
+
+ pre = g_new (PreRead, 1);
+ pre->data = io_op->io_buffer;
+ pre->len = io_op->io_res;
+ pre->seek_generation = file->input_block_seek_generation;
+
+ file->pre_reads = g_list_append (file->pre_reads, pre);
+ }
+ else
+ g_free (io_op->io_buffer);
+
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+
+ /* read header data, (or manual io_len/res = 0) */
+ case QUERY_STATE_HANDLE_HEADER:
+ if (io_op->io_cancelled)
+ {
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = file->input_buffer->len == 0 && !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->info = NULL;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA)
+ {
+ g_string_truncate (file->input_buffer, 0);
+ file->input_state = INPUT_STATE_IN_BLOCK;
+ file->input_block_size = reply.arg1;
+ file->input_block_seek_generation = reply.arg2;
+ op->state = QUERY_STATE_HANDLE_INPUT_BLOCK;
+ break;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO)
+ {
+ op->info = gvfs_file_info_demarshal (data, reply.arg2);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = QUERY_STATE_HANDLE_HEADER;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+
+static GFileInfo *
+g_daemon_file_input_stream_query_info (GFileInputStream *stream,
+ const char *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileInputStream *file;
+ QueryOperation op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return NULL;
+
+ memset (&op, 0, sizeof (op));
+ op.state = QUERY_STATE_INIT;
+ if (attributes)
+ op.attributes = (char *)attributes;
+ else
+ op.attributes = "";
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_query_state_machine,
+ &op, cancellable, error))
+ return NULL; /* IO Error */
+
+ if (op.info == NULL)
+ g_propagate_error (error, op.ret_error);
+
+ return op.info;
+}
+
+
+/************************************************************************
+ * Async I/O Code *
+ ************************************************************************/
+
+typedef struct AsyncIterator AsyncIterator;
+
+typedef void (*AsyncIteratorDone) (GInputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer callback_data,
+ GError *io_error);
+
+struct AsyncIterator {
+ AsyncIteratorDone done_cb;
+ GDaemonFileInputStream *file;
+ GCancellable *cancellable;
+ IOOperationData io_data;
+ state_machine_iterator iterator;
+ gpointer iterator_data;
+ int io_priority;
+ GAsyncReadyCallback callback;
+ gpointer callback_data;
+};
+
+static void async_iterate (AsyncIterator *iterator);
+
+static void
+async_iterator_done (AsyncIterator *iterator, GError *io_error)
+{
+ iterator->done_cb (G_INPUT_STREAM (iterator->file),
+ iterator->iterator_data,
+ iterator->callback,
+ iterator->callback_data,
+ io_error);
+
+ g_free (iterator);
+
+}
+
+static void
+async_op_handle (AsyncIterator *iterator,
+ gssize res,
+ GError *io_error)
+{
+ IOOperationData *io_data = &iterator->io_data;
+ GError *error;
+
+ if (io_error != NULL)
+ {
+ if (error_is_cancel (io_error))
+ {
+ io_data->io_res = 0;
+ io_data->io_cancelled = TRUE;
+ }
+ else
+ {
+ error = NULL;
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), io_error->message);
+ async_iterator_done (iterator, error);
+ g_error_free (error);
+ return;
+ }
+ }
+ else if (res == 0 && io_data->io_size != 0)
+ {
+ error = NULL;
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), _("End of stream"));
+ async_iterator_done (iterator, error);
+ g_error_free (error);
+ return;
+ }
+ else
+ {
+ io_data->io_res = res;
+ io_data->io_cancelled = FALSE;
+ }
+
+ async_iterate (iterator);
+}
+
+static void
+async_read_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ gssize count_read;
+ GError *error = NULL;
+
+ count_read = g_input_stream_read_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, count_read, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_skip_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ gssize count_skipped;
+ GError *error = NULL;
+
+ count_skipped = g_input_stream_skip_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, count_skipped, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_write_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GOutputStream *stream = G_OUTPUT_STREAM (source_object);
+ gssize bytes_written;
+ GError *error = NULL;
+
+ bytes_written = g_output_stream_write_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, bytes_written, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_iterate (AsyncIterator *iterator)
+{
+ IOOperationData *io_data = &iterator->io_data;
+ GDaemonFileInputStream *file = iterator->file;
+ StateOp io_op;
+
+ io_data->cancelled =
+ g_cancellable_is_cancelled (iterator->cancellable);
+
+ io_op = iterator->iterator (file, io_data, iterator->iterator_data);
+
+ if (io_op == STATE_OP_DONE)
+ {
+ async_iterator_done (iterator, NULL);
+ return;
+ }
+
+ /* TODO: Handle allow_cancel... */
+
+ if (io_op == STATE_OP_READ)
+ {
+ g_input_stream_read_async (file->data_stream,
+ io_data->io_buffer, io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_read_op_callback, iterator);
+ }
+ else if (io_op == STATE_OP_SKIP)
+ {
+ g_input_stream_skip_async (file->data_stream,
+ io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_skip_op_callback, iterator);
+ }
+ else if (io_op == STATE_OP_WRITE)
+ {
+ g_output_stream_write_async (file->command_stream,
+ io_data->io_buffer, io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_write_op_callback, iterator);
+ }
+ else
+ g_assert_not_reached ();
+}
+
+static void
+run_async_state_machine (GDaemonFileInputStream *file,
+ state_machine_iterator iterator_cb,
+ gpointer iterator_data,
+ int io_priority,
+ GAsyncReadyCallback callback,
+ gpointer data,
+ GCancellable *cancellable,
+ AsyncIteratorDone done_cb)
+{
+ AsyncIterator *iterator;
+
+ iterator = g_new0 (AsyncIterator, 1);
+ iterator->file = file;
+ iterator->iterator = iterator_cb;
+ iterator->iterator_data = iterator_data;
+ iterator->io_priority = io_priority;
+ iterator->cancellable = cancellable;
+ iterator->callback = callback;
+ iterator->callback_data = data;
+ iterator->done_cb = done_cb;
+
+ async_iterate (iterator);
+}
+
+static void
+async_read_done (GInputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ ReadOperation *op;
+ gssize count_read;
+ GError *error;
+ GSimpleAsyncResult *simple;
+
+ op = op_data;
+
+ if (io_error)
+ {
+ count_read = -1;
+ error = io_error;
+ }
+ else
+ {
+ count_read = op->ret_val;
+ error = op->ret_error;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_input_stream_read_async);
+
+ g_simple_async_result_set_op_res_gssize (simple, count_read);
+
+ if (count_read == -1)
+ g_simple_async_result_set_from_error (simple, error);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op);
+}
+
+static void
+g_daemon_file_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFileInputStream *file;
+ ReadOperation *op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ /* Limit for sanity and to avoid 32bit overflow */
+ if (count > MAX_READ_SIZE)
+ count = MAX_READ_SIZE;
+
+ op = g_new0 (ReadOperation, 1);
+ op->state = READ_STATE_INIT;
+ op->buffer = buffer;
+ op->buffer_size = count;
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_read_state_machine,
+ op,
+ io_priority,
+ callback, user_data,
+ cancellable,
+ async_read_done);
+}
+
+static gssize
+g_daemon_file_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gssize nread;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_input_stream_read_async);
+
+ nread = g_simple_async_result_get_op_res_gssize (simple);
+ return nread;
+}
+
+
+static void
+g_daemon_file_input_stream_skip_async (GInputStream *stream,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ g_assert_not_reached ();
+ /* TODO: Not implemented */
+}
+
+static gssize
+g_daemon_file_input_stream_skip_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert_not_reached ();
+ /* TODO: Not implemented */
+}
+
+static void
+async_close_done (GInputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ GDaemonFileInputStream *file;
+ GSimpleAsyncResult *simple;
+ CloseOperation *op;
+ gboolean result;
+ GError *error;
+ GCancellable *cancellable = NULL; /* TODO: get cancellable */
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ op = op_data;
+
+ if (io_error)
+ {
+ result = FALSE;
+ error = io_error;
+ }
+ else
+ {
+ result = op->ret_val;
+ error = op->ret_error;
+ }
+
+ if (result)
+ result = g_output_stream_close (file->command_stream, cancellable, &error);
+ else
+ g_output_stream_close (file->command_stream, cancellable, NULL);
+
+ if (result)
+ result = g_input_stream_close (file->data_stream, cancellable, &error);
+ else
+ g_input_stream_close (file->data_stream, cancellable, NULL);
+
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_input_stream_read_async);
+
+ if (!result)
+ g_simple_async_result_set_from_error (simple, error);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op);
+}
+
+static void
+g_daemon_file_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ GDaemonFileInputStream *file;
+ CloseOperation *op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ op = g_new0 (CloseOperation, 1);
+ op->state = CLOSE_STATE_INIT;
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_close_state_machine,
+ op, io_priority,
+ callback, data,
+ cancellable,
+ async_close_done);
+}
+
+static gboolean
+g_daemon_file_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
+
+static void
+async_query_done (GInputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ GDaemonFileInputStream *file;
+ GSimpleAsyncResult *simple;
+ QueryOperation *op;
+ GFileInfo *info;
+ GError *error;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ op = op_data;
+
+ if (io_error)
+ {
+ info = NULL;
+ error = io_error;
+ }
+ else
+ {
+ info = op->info;
+ error = op->ret_error;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_input_stream_query_info_async);
+
+ if (info == NULL)
+ g_simple_async_result_set_from_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple, info,
+ g_object_unref);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op->attributes);
+ g_free (op);
+}
+
+static void
+g_daemon_file_input_stream_query_info_async (GFileInputStream *stream,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFileInputStream *file;
+ QueryOperation *op;
+
+ file = G_DAEMON_FILE_INPUT_STREAM (stream);
+
+ op = g_new0 (QueryOperation, 1);
+ op->state = QUERY_STATE_INIT;
+ if (attributes)
+ op->attributes = g_strdup (attributes);
+ else
+ op->attributes = g_strdup ("");
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_query_state_machine,
+ op, io_priority,
+ callback, user_data,
+ cancellable,
+ async_query_done);
+}
+
+static GFileInfo *
+g_daemon_file_input_stream_query_info_finish (GFileInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ GFileInfo *info;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_input_stream_query_info_async);
+
+ info = g_simple_async_result_get_op_res_gpointer (simple);
+
+ return g_object_ref (info);
+
+}
diff --git a/trunk/client/gdaemonfileinputstream.h b/trunk/client/gdaemonfileinputstream.h
new file mode 100644
index 00000000..2d4cc4ce
--- /dev/null
+++ b/trunk/client/gdaemonfileinputstream.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_FILE_INPUT_STREAM_H__
+#define __G_DAEMON_FILE_INPUT_STREAM_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_FILE_INPUT_STREAM (g_daemon_file_input_stream_get_type ())
+#define G_DAEMON_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStream))
+#define G_DAEMON_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStreamClass))
+#define G_IS_DAEMON_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM))
+#define G_IS_DAEMON_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_INPUT_STREAM))
+#define G_DAEMON_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_INPUT_STREAM, GDaemonFileInputStreamClass))
+
+typedef struct _GDaemonFileInputStream GDaemonFileInputStream;
+typedef struct _GDaemonFileInputStreamClass GDaemonFileInputStreamClass;
+
+struct _GDaemonFileInputStreamClass
+{
+ GFileInputStreamClass parent_class;
+};
+
+GType g_daemon_file_input_stream_get_type (void) G_GNUC_CONST;
+
+GFileInputStream *g_daemon_file_input_stream_new (int fd,
+ gboolean can_seek);
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_FILE_INPUT_STREAM_H__ */
diff --git a/trunk/client/gdaemonfilemonitor.c b/trunk/client/gdaemonfilemonitor.c
new file mode 100644
index 00000000..851907a9
--- /dev/null
+++ b/trunk/client/gdaemonfilemonitor.c
@@ -0,0 +1,216 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "gdaemonfilemonitor.h"
+#include <gio/gio.h>
+#include <gvfsdaemondbus.h>
+#include <gvfsdaemonprotocol.h>
+#include "gdbusutils.h"
+#include "gmountspec.h"
+#include "gdaemonfile.h"
+
+#define OBJ_PATH_PREFIX "/org/gtk/vfs/client/filemonitor/"
+
+/* atomic */
+static volatile gint path_counter = 1;
+
+static gboolean g_daemon_file_monitor_cancel (GFileMonitor* monitor);
+static DBusHandlerResult g_daemon_file_monitor_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+
+struct _GDaemonFileMonitor
+{
+ GFileMonitor parent_instance;
+
+ char *object_path;
+ char *remote_obj_path;
+ char *remote_id;
+};
+
+G_DEFINE_TYPE (GDaemonFileMonitor, g_daemon_file_monitor, G_TYPE_FILE_MONITOR)
+
+static void
+g_daemon_file_monitor_finalize (GObject* object)
+{
+ GDaemonFileMonitor *daemon_monitor;
+
+ daemon_monitor = G_DAEMON_FILE_MONITOR (object);
+
+ _g_dbus_unregister_vfs_filter (daemon_monitor->object_path);
+
+ g_free (daemon_monitor->object_path);
+ g_free (daemon_monitor->remote_id);
+ g_free (daemon_monitor->remote_obj_path);
+
+ if (G_OBJECT_CLASS (g_daemon_file_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_file_monitor_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_file_monitor_class_init (GDaemonFileMonitorClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
+ GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_file_monitor_finalize;
+
+ file_monitor_class->cancel = g_daemon_file_monitor_cancel;
+}
+
+static void
+g_daemon_file_monitor_init (GDaemonFileMonitor* daemon_monitor)
+{
+ gint id;
+
+ id = g_atomic_int_exchange_and_add (&path_counter, 1);
+
+ daemon_monitor->object_path = g_strdup_printf (OBJ_PATH_PREFIX"%d", id);
+
+ _g_dbus_register_vfs_filter (daemon_monitor->object_path,
+ g_daemon_file_monitor_dbus_filter,
+ G_OBJECT (daemon_monitor));
+}
+
+GFileMonitor*
+g_daemon_file_monitor_new (const char *remote_id,
+ const char *remote_obj_path)
+{
+ GDaemonFileMonitor* daemon_monitor;
+ DBusMessage *message;
+
+ daemon_monitor = g_object_new (G_TYPE_DAEMON_FILE_MONITOR, NULL);
+
+ daemon_monitor->remote_id = g_strdup (remote_id);
+ daemon_monitor->remote_obj_path = g_strdup (remote_obj_path);
+
+ message =
+ dbus_message_new_method_call (daemon_monitor->remote_id,
+ daemon_monitor->remote_obj_path,
+ G_VFS_DBUS_MONITOR_INTERFACE,
+ G_VFS_DBUS_MONITOR_OP_SUBSCRIBE);
+
+ _g_dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH,
+ &daemon_monitor->object_path, 0);
+
+ _g_vfs_daemon_call_async (message,
+ NULL, NULL,
+ NULL);
+
+ dbus_message_unref (message);
+
+ return G_FILE_MONITOR (daemon_monitor);
+}
+
+static DBusHandlerResult
+g_daemon_file_monitor_dbus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GDaemonFileMonitor *monitor = G_DAEMON_FILE_MONITOR (user_data);
+ const char *member;
+ guint32 event_type;
+ DBusMessageIter iter;
+ GMountSpec *spec1, *spec2;
+ char *path1, *path2;
+ GFile *file1, *file2;
+
+ member = dbus_message_get_member (message);
+
+ if (strcmp (member, G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED) == 0)
+ {
+ dbus_message_iter_init (message, &iter);
+
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_UINT32, &event_type,
+ 0))
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+ spec1 = g_mount_spec_from_dbus (&iter);
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ G_DBUS_TYPE_CSTRING, &path1,
+ 0))
+ {
+ g_mount_spec_unref (spec1);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ file1 = g_daemon_file_new (spec1, path1);
+
+ g_mount_spec_unref (spec1);
+ g_free (path1);
+
+ file2 = NULL;
+
+ spec2 = g_mount_spec_from_dbus (&iter);
+ if (spec2) {
+ if (_g_dbus_message_iter_get_args (&iter, NULL,
+ G_DBUS_TYPE_CSTRING, &path2,
+ 0))
+ {
+ file2 = g_daemon_file_new (spec2, path2);
+
+ g_free (path2);
+ }
+
+ g_mount_spec_unref (spec2);
+ }
+
+ g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
+ file1, file2,
+ event_type);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static gboolean
+g_daemon_file_monitor_cancel (GFileMonitor* monitor)
+{
+ GDaemonFileMonitor *daemon_monitor = G_DAEMON_FILE_MONITOR (monitor);
+ DBusMessage *message;
+
+ message =
+ dbus_message_new_method_call (daemon_monitor->remote_id,
+ daemon_monitor->remote_obj_path,
+ G_VFS_DBUS_MONITOR_INTERFACE,
+ G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE);
+
+ _g_dbus_message_append_args (message, DBUS_TYPE_OBJECT_PATH,
+ &daemon_monitor->object_path, 0);
+
+ _g_vfs_daemon_call_async (message,
+ NULL, NULL,
+ NULL);
+
+ dbus_message_unref (message);
+
+ return TRUE;
+}
+
diff --git a/trunk/client/gdaemonfilemonitor.h b/trunk/client/gdaemonfilemonitor.h
new file mode 100644
index 00000000..9cd02175
--- /dev/null
+++ b/trunk/client/gdaemonfilemonitor.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_FILE_MONITOR_H__
+#define __G_DAEMON_FILE_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_FILE_MONITOR (g_daemon_file_monitor_get_type ())
+#define G_DAEMON_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_MONITOR, GDaemonFileMonitor))
+#define G_DAEMON_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_DAEMON_FILE_MONITOR, GDaemonFileMonitorClass))
+#define G_IS_DAEMON_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_MONITOR))
+#define G_IS_DAEMON_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_MONITOR))
+
+typedef struct _GDaemonFileMonitor GDaemonFileMonitor;
+typedef struct _GDaemonFileMonitorClass GDaemonFileMonitorClass;
+
+struct _GDaemonFileMonitorClass {
+ GFileMonitorClass parent_class;
+};
+
+GType g_daemon_file_monitor_get_type (void) G_GNUC_CONST;
+
+GFileMonitor* g_daemon_file_monitor_new (const char *remote_id,
+ const char *remote_obj_path);
+
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_FILE_MONITOR_H__ */
diff --git a/trunk/client/gdaemonfileoutputstream.c b/trunk/client/gdaemonfileoutputstream.c
new file mode 100644
index 00000000..27992bf8
--- /dev/null
+++ b/trunk/client/gdaemonfileoutputstream.c
@@ -0,0 +1,1647 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include "gdaemonfileoutputstream.h"
+#include "gvfsdaemondbus.h"
+#include <gvfsdaemonprotocol.h>
+#include <gvfsfileinfo.h>
+
+#define MAX_WRITE_SIZE (4*1024*1024)
+
+typedef enum {
+ STATE_OP_DONE,
+ STATE_OP_READ,
+ STATE_OP_WRITE,
+ STATE_OP_SKIP
+} StateOp;
+
+typedef enum {
+ WRITE_STATE_INIT = 0,
+ WRITE_STATE_WROTE_COMMAND,
+ WRITE_STATE_SEND_DATA,
+ WRITE_STATE_HANDLE_INPUT
+} WriteState;
+
+typedef struct {
+ WriteState state;
+
+ /* Output */
+ const char *buffer;
+ gsize buffer_size;
+ gsize buffer_pos;
+
+ /* Input */
+ gssize ret_val;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} WriteOperation;
+
+typedef enum {
+ SEEK_STATE_INIT = 0,
+ SEEK_STATE_WROTE_REQUEST,
+ SEEK_STATE_HANDLE_INPUT
+} SeekState;
+
+typedef struct {
+ SeekState state;
+
+ /* Output */
+ goffset offset;
+ GSeekType seek_type;
+ /* Output */
+ gboolean ret_val;
+ GError *ret_error;
+ goffset ret_offset;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} SeekOperation;
+
+typedef enum {
+ CLOSE_STATE_INIT = 0,
+ CLOSE_STATE_WROTE_REQUEST,
+ CLOSE_STATE_HANDLE_INPUT
+} CloseState;
+
+typedef struct {
+ CloseState state;
+
+ /* Output */
+
+ /* Output */
+ gboolean ret_val;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} CloseOperation;
+
+typedef enum {
+ QUERY_STATE_INIT = 0,
+ QUERY_STATE_WROTE_REQUEST,
+ QUERY_STATE_HANDLE_INPUT,
+} QueryState;
+
+typedef struct {
+ QueryState state;
+
+ /* Input */
+ char *attributes;
+
+ /* Output */
+ GFileInfo *info;
+ GError *ret_error;
+
+ gboolean sent_cancel;
+
+ guint32 seq_nr;
+} QueryOperation;
+
+typedef struct {
+ gboolean cancelled;
+
+ char *io_buffer;
+ gsize io_size;
+ gsize io_res;
+ /* The operation always succeeds, or gets cancelled.
+ If we get an error doing the i/o that is considered fatal */
+ gboolean io_allow_cancel;
+ gboolean io_cancelled;
+} IOOperationData;
+
+typedef StateOp (*state_machine_iterator) (GDaemonFileOutputStream *file, IOOperationData *io_op, gpointer data);
+
+struct _GDaemonFileOutputStream {
+ GFileOutputStream parent;
+
+ GOutputStream *command_stream;
+ GInputStream *data_stream;
+ guint can_seek : 1;
+
+ guint32 seq_nr;
+ goffset current_offset;
+
+ gsize input_block_size;
+ GString *input_buffer;
+
+ GString *output_buffer;
+
+ char *etag;
+
+};
+
+static gssize g_daemon_file_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean g_daemon_file_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static GFileInfo *g_daemon_file_output_stream_query_info (GFileOutputStream *stream,
+ const char *attributes,
+ GCancellable *cancellable,
+ GError **error);
+static char *g_daemon_file_output_stream_get_etag (GFileOutputStream *stream);
+static goffset g_daemon_file_output_stream_tell (GFileOutputStream *stream);
+static gboolean g_daemon_file_output_stream_can_seek (GFileOutputStream *stream);
+static gboolean g_daemon_file_output_stream_seek (GFileOutputStream *stream,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error);
+static void g_daemon_file_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize g_daemon_file_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_daemon_file_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean g_daemon_file_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void g_daemon_file_output_stream_query_info_async (GFileOutputStream *stream,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+static GFileInfo *g_daemon_file_output_stream_query_info_finish (GFileOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+
+
+G_DEFINE_TYPE (GDaemonFileOutputStream, g_daemon_file_output_stream,
+ G_TYPE_FILE_OUTPUT_STREAM)
+
+static void
+g_string_remove_in_front (GString *string,
+ gsize bytes)
+{
+ memmove (string->str,
+ string->str + bytes,
+ string->len - bytes);
+ g_string_truncate (string,
+ string->len - bytes);
+}
+
+static void
+g_daemon_file_output_stream_finalize (GObject *object)
+{
+ GDaemonFileOutputStream *file;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (object);
+
+ if (file->command_stream)
+ g_object_unref (file->command_stream);
+ if (file->data_stream)
+ g_object_unref (file->data_stream);
+
+ g_string_free (file->input_buffer, TRUE);
+ g_string_free (file->output_buffer, TRUE);
+
+ g_free (file->etag);
+
+ if (G_OBJECT_CLASS (g_daemon_file_output_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_file_output_stream_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_file_output_stream_class_init (GDaemonFileOutputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+ GFileOutputStreamClass *file_stream_class = G_FILE_OUTPUT_STREAM_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_file_output_stream_finalize;
+
+ stream_class->write_fn = g_daemon_file_output_stream_write;
+ stream_class->close_fn = g_daemon_file_output_stream_close;
+
+ stream_class->write_async = g_daemon_file_output_stream_write_async;
+ stream_class->write_finish = g_daemon_file_output_stream_write_finish;
+ stream_class->close_async = g_daemon_file_output_stream_close_async;
+ stream_class->close_finish = g_daemon_file_output_stream_close_finish;
+
+ file_stream_class->tell = g_daemon_file_output_stream_tell;
+ file_stream_class->can_seek = g_daemon_file_output_stream_can_seek;
+ file_stream_class->seek = g_daemon_file_output_stream_seek;
+ file_stream_class->query_info = g_daemon_file_output_stream_query_info;
+ file_stream_class->get_etag = g_daemon_file_output_stream_get_etag;
+ file_stream_class->query_info_async = g_daemon_file_output_stream_query_info_async;
+ file_stream_class->query_info_finish = g_daemon_file_output_stream_query_info_finish;
+}
+
+static void
+g_daemon_file_output_stream_init (GDaemonFileOutputStream *info)
+{
+ info->output_buffer = g_string_new ("");
+ info->input_buffer = g_string_new ("");
+ info->seq_nr = 1;
+}
+
+GFileOutputStream *
+g_daemon_file_output_stream_new (int fd,
+ gboolean can_seek,
+ goffset initial_offset)
+{
+ GDaemonFileOutputStream *stream;
+
+ stream = g_object_new (G_TYPE_DAEMON_FILE_OUTPUT_STREAM, NULL);
+
+ stream->command_stream = g_unix_output_stream_new (fd, FALSE);
+ stream->data_stream = g_unix_input_stream_new (fd, TRUE);
+ stream->can_seek = can_seek;
+ stream->current_offset = initial_offset;
+
+ return G_FILE_OUTPUT_STREAM (stream);
+}
+
+static gboolean
+error_is_cancel (GError *error)
+{
+ return error != NULL &&
+ error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_CANCELLED;
+}
+
+static void
+append_request (GDaemonFileOutputStream *stream, guint32 command,
+ guint32 arg1, guint32 arg2, guint32 data_len, guint32 *seq_nr)
+{
+ GVfsDaemonSocketProtocolRequest cmd;
+
+ g_assert (sizeof (cmd) == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE);
+
+ if (seq_nr)
+ *seq_nr = stream->seq_nr;
+
+ cmd.command = g_htonl (command);
+ cmd.seq_nr = g_htonl (stream->seq_nr);
+ cmd.arg1 = g_htonl (arg1);
+ cmd.arg2 = g_htonl (arg2);
+ cmd.data_len = g_htonl (data_len);
+
+ stream->seq_nr++;
+
+ g_string_append_len (stream->output_buffer,
+ (char *)&cmd, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE);
+}
+
+static gsize
+get_reply_header_missing_bytes (GString *buffer)
+{
+ GVfsDaemonSocketProtocolReply *reply;
+ guint32 type;
+ guint32 arg2;
+
+ if (buffer->len < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE)
+ return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE - buffer->len;
+
+ reply = (GVfsDaemonSocketProtocolReply *)buffer->str;
+
+ type = g_ntohl (reply->type);
+ arg2 = g_ntohl (reply->arg2);
+
+ /* ERROR, CLOSED and INFO has extra data w/ len in arg2 */
+ if (type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR ||
+ type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED ||
+ type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO)
+ return G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + arg2 - buffer->len;
+ return 0;
+}
+
+static char *
+decode_reply (GString *buffer, GVfsDaemonSocketProtocolReply *reply_out)
+{
+ GVfsDaemonSocketProtocolReply *reply;
+ reply = (GVfsDaemonSocketProtocolReply *)buffer->str;
+ reply_out->type = g_ntohl (reply->type);
+ reply_out->seq_nr = g_ntohl (reply->seq_nr);
+ reply_out->arg1 = g_ntohl (reply->arg1);
+ reply_out->arg2 = g_ntohl (reply->arg2);
+
+ return buffer->str + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE;
+}
+
+static void
+decode_error (GVfsDaemonSocketProtocolReply *reply, char *data, GError **error)
+{
+ g_set_error_literal (error,
+ g_quark_from_string (data),
+ reply->arg1,
+ data + strlen (data) + 1);
+}
+
+
+static gboolean
+run_sync_state_machine (GDaemonFileOutputStream *file,
+ state_machine_iterator iterator,
+ gpointer data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gssize res;
+ StateOp io_op;
+ IOOperationData io_data;
+ GError *io_error;
+
+ memset (&io_data, 0, sizeof (io_data));
+
+ while (TRUE)
+ {
+ if (cancellable)
+ io_data.cancelled = g_cancellable_is_cancelled (cancellable);
+
+ io_op = iterator (file, &io_data, data);
+
+ if (io_op == STATE_OP_DONE)
+ return TRUE;
+
+ io_error = NULL;
+ if (io_op == STATE_OP_READ)
+ {
+ res = g_input_stream_read (file->data_stream,
+ io_data.io_buffer, io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else if (io_op == STATE_OP_SKIP)
+ {
+ res = g_input_stream_skip (file->data_stream,
+ io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else if (io_op == STATE_OP_WRITE)
+ {
+ res = g_output_stream_write (file->command_stream,
+ io_data.io_buffer, io_data.io_size,
+ io_data.io_allow_cancel ? cancellable : NULL,
+ &io_error);
+ }
+ else
+ {
+ res = 0;
+ g_assert_not_reached ();
+ }
+
+ if (res == -1)
+ {
+ if (error_is_cancel (io_error))
+ {
+ io_data.io_res = 0;
+ io_data.io_cancelled = TRUE;
+ g_error_free (io_error);
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), io_error->message);
+ g_error_free (io_error);
+ return FALSE;
+ }
+ }
+ else if (res == 0 && io_data.io_size != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), _("End of stream"));
+ return FALSE;
+ }
+ else
+ {
+ io_data.io_res = res;
+ io_data.io_cancelled = FALSE;
+ }
+ }
+}
+
+/* read cycle:
+
+ if we know of a (partially read) matching outstanding block, read from it
+ create packet, append to outgoing
+ flush outgoing
+ start processing output, looking for a data block with same seek gen,
+ or an error with same seq nr
+ on cancel, send cancel command and go back to loop
+ */
+
+static StateOp
+iterate_write_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, WriteOperation *op)
+{
+ gsize len;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case WRITE_STATE_INIT:
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE,
+ op->buffer_size, 0, op->buffer_size, &op->seq_nr);
+ op->state = WRITE_STATE_WROTE_COMMAND;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case WRITE_STATE_WROTE_COMMAND:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = -1;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->buffer_pos = 0;
+ if (op->sent_cancel)
+ op->state = WRITE_STATE_HANDLE_INPUT;
+ else
+ op->state = WRITE_STATE_SEND_DATA;
+ break;
+
+ /* No op */
+ case WRITE_STATE_SEND_DATA:
+ op->buffer_pos += io_op->io_res;
+
+ if (op->buffer_pos < op->buffer_size)
+ {
+ io_op->io_buffer = (char *)(op->buffer + op->buffer_pos);
+ io_op->io_size = op->buffer_size - op->buffer_pos;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ op->state = WRITE_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case WRITE_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = WRITE_STATE_WROTE_COMMAND;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = -1;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN)
+ {
+ op->ret_val = reply.arg1;
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = WRITE_STATE_HANDLE_INPUT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+
+ }
+}
+
+static gssize
+g_daemon_file_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileOutputStream *file;
+ WriteOperation op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ /* Limit for sanity and to avoid 32bit overflow */
+ if (count > MAX_WRITE_SIZE)
+ count = MAX_WRITE_SIZE;
+
+ memset (&op, 0, sizeof (op));
+ op.state = WRITE_STATE_INIT;
+ op.buffer = buffer;
+ op.buffer_size = count;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_write_state_machine,
+ &op, cancellable, error))
+ return -1; /* IO Error */
+
+ if (op.ret_val == -1)
+ g_propagate_error (error, op.ret_error);
+ else
+ file->current_offset += op.ret_val;
+
+ return op.ret_val;
+}
+
+static StateOp
+iterate_close_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, CloseOperation *op)
+{
+ gsize len;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case CLOSE_STATE_INIT:
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE,
+ 0, 0, 0, &op->seq_nr);
+ op->state = CLOSE_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case CLOSE_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = FALSE;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case CLOSE_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = CLOSE_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = FALSE;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED)
+ {
+ op->ret_val = TRUE;
+ if (reply.arg2 > 0)
+ file->etag = g_strndup (data, reply.arg2);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = CLOSE_STATE_HANDLE_INPUT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+
+static gboolean
+g_daemon_file_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileOutputStream *file;
+ CloseOperation op;
+ gboolean res;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ /* We need to do a full roundtrip to guarantee that the writes have
+ reached the disk. */
+
+ memset (&op, 0, sizeof (op));
+ op.state = CLOSE_STATE_INIT;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_close_state_machine,
+ &op, cancellable, error))
+ res = FALSE;
+ else
+ {
+ if (!op.ret_val)
+ g_propagate_error (error, op.ret_error);
+ res = op.ret_val;
+ }
+
+ /* Return the first error, but close all streams */
+ if (res)
+ res = g_output_stream_close (file->command_stream, cancellable, error);
+ else
+ g_output_stream_close (file->command_stream, cancellable, NULL);
+
+ if (res)
+ res = g_input_stream_close (file->data_stream, cancellable, error);
+ else
+ g_input_stream_close (file->data_stream, cancellable, NULL);
+
+ return res;
+}
+
+static goffset
+g_daemon_file_output_stream_tell (GFileOutputStream *stream)
+{
+ GDaemonFileOutputStream *file;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ return file->current_offset;
+}
+
+static gboolean
+g_daemon_file_output_stream_can_seek (GFileOutputStream *stream)
+{
+ GDaemonFileOutputStream *file;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ return file->can_seek;
+}
+
+static StateOp
+iterate_seek_state_machine (GDaemonFileOutputStream *file, IOOperationData *io_op, SeekOperation *op)
+{
+ gsize len;
+ guint32 request;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case SEEK_STATE_INIT:
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET;
+ if (op->seek_type == G_SEEK_CUR)
+ op->offset = file->current_offset + op->offset;
+ else if (op->seek_type == G_SEEK_END)
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END;
+ append_request (file, request,
+ op->offset & 0xffffffff,
+ op->offset >> 32,
+ 0,
+ &op->seq_nr);
+ op->state = SEEK_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case SEEK_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->ret_val = -1;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case SEEK_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = SEEK_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->ret_val = FALSE;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS)
+ {
+ op->ret_val = TRUE;
+ op->ret_offset = ((goffset)reply.arg2) << 32 | (goffset)reply.arg1;
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+static gboolean
+g_daemon_file_output_stream_seek (GFileOutputStream *stream,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileOutputStream *file;
+ SeekOperation op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ if (!file->can_seek)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Seek not supported on stream"));
+ return FALSE;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ memset (&op, 0, sizeof (op));
+ op.state = SEEK_STATE_INIT;
+ op.offset = offset;
+ op.seek_type = type;
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_seek_state_machine,
+ &op, cancellable, error))
+ return FALSE; /* IO Error */
+
+ if (!op.ret_val)
+ g_propagate_error (error, op.ret_error);
+ else
+ file->current_offset = op.ret_offset;
+
+ return op.ret_val;
+}
+
+static char *
+g_daemon_file_output_stream_get_etag (GFileOutputStream *stream)
+{
+ GDaemonFileOutputStream *file;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ return g_strdup (file->etag);
+}
+
+static StateOp
+iterate_query_state_machine (GDaemonFileOutputStream *file,
+ IOOperationData *io_op,
+ QueryOperation *op)
+{
+ gsize len;
+ guint32 request;
+
+ while (TRUE)
+ {
+ switch (op->state)
+ {
+ /* Initial state for read op */
+ case QUERY_STATE_INIT:
+ request = G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_QUERY_INFO;
+ append_request (file, request,
+ 0,
+ 0,
+ strlen (op->attributes),
+ &op->seq_nr);
+ g_string_append (file->output_buffer,
+ op->attributes);
+
+ op->state = QUERY_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = TRUE; /* Allow cancel before first byte of request sent */
+ return STATE_OP_WRITE;
+
+ /* wrote parts of output_buffer */
+ case QUERY_STATE_WROTE_REQUEST:
+ if (io_op->io_cancelled)
+ {
+ op->info = NULL;
+ g_set_error_literal (&op->ret_error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return STATE_OP_DONE;
+ }
+
+ if (io_op->io_res < file->output_buffer->len)
+ {
+ g_string_remove_in_front (file->output_buffer,
+ io_op->io_res);
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+ g_string_truncate (file->output_buffer, 0);
+
+ op->state = QUERY_STATE_HANDLE_INPUT;
+ break;
+
+ /* No op */
+ case QUERY_STATE_HANDLE_INPUT:
+ if (io_op->cancelled && !op->sent_cancel)
+ {
+ op->sent_cancel = TRUE;
+ append_request (file, G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL,
+ op->seq_nr, 0, 0, NULL);
+ op->state = QUERY_STATE_WROTE_REQUEST;
+ io_op->io_buffer = file->output_buffer->str;
+ io_op->io_size = file->output_buffer->len;
+ io_op->io_allow_cancel = FALSE;
+ return STATE_OP_WRITE;
+ }
+
+
+ if (io_op->io_res > 0)
+ {
+ gsize unread_size = io_op->io_size - io_op->io_res;
+ g_string_set_size (file->input_buffer,
+ file->input_buffer->len - unread_size);
+ }
+
+ len = get_reply_header_missing_bytes (file->input_buffer);
+ if (len > 0)
+ {
+ gsize current_len = file->input_buffer->len;
+ g_string_set_size (file->input_buffer,
+ current_len + len);
+ io_op->io_buffer = file->input_buffer->str + current_len;
+ io_op->io_size = len;
+ io_op->io_allow_cancel = !op->sent_cancel;
+ return STATE_OP_READ;
+ }
+
+ /* Got full header */
+
+ {
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ data = decode_reply (file->input_buffer, &reply);
+
+ if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR &&
+ reply.seq_nr == op->seq_nr)
+ {
+ op->info = NULL;
+ decode_error (&reply, data, &op->ret_error);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ else if (reply.type == G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO)
+ {
+ op->info = gvfs_file_info_demarshal (data, reply.arg2);
+ g_string_truncate (file->input_buffer, 0);
+ return STATE_OP_DONE;
+ }
+ /* Ignore other reply types */
+ }
+
+ g_string_truncate (file->input_buffer, 0);
+
+ /* This wasn't interesting, read next reply */
+ op->state = SEEK_STATE_HANDLE_INPUT;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Clear io_op between non-op state switches */
+ io_op->io_size = 0;
+ io_op->io_res = 0;
+ io_op->io_cancelled = FALSE;
+ }
+}
+
+static GFileInfo *
+g_daemon_file_output_stream_query_info (GFileOutputStream *stream,
+ const char *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFileOutputStream *file;
+ QueryOperation op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return NULL;
+
+ memset (&op, 0, sizeof (op));
+ op.state = QUERY_STATE_INIT;
+ if (attributes)
+ op.attributes = (char *)attributes;
+ else
+ op.attributes = "";
+
+ if (!run_sync_state_machine (file, (state_machine_iterator)iterate_query_state_machine,
+ &op, cancellable, error))
+ return NULL; /* IO Error */
+
+ if (op.info == NULL)
+ g_propagate_error (error, op.ret_error);
+
+ return op.info;
+}
+
+/************************************************************************
+ * Async I/O Code *
+ ************************************************************************/
+
+typedef struct AsyncIterator AsyncIterator;
+
+typedef void (*AsyncIteratorDone) (GOutputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer callback_data,
+ GError *io_error);
+
+struct AsyncIterator {
+ AsyncIteratorDone done_cb;
+ GDaemonFileOutputStream *file;
+ GCancellable *cancellable;
+ IOOperationData io_data;
+ state_machine_iterator iterator;
+ gpointer iterator_data;
+ int io_priority;
+ GAsyncReadyCallback callback;
+ gpointer callback_data;
+};
+
+static void async_iterate (AsyncIterator *iterator);
+
+static void
+async_iterator_done (AsyncIterator *iterator, GError *io_error)
+{
+ iterator->done_cb (G_OUTPUT_STREAM (iterator->file),
+ iterator->iterator_data,
+ iterator->callback,
+ iterator->callback_data,
+ io_error);
+
+ g_free (iterator);
+
+}
+
+static void
+async_op_handle (AsyncIterator *iterator,
+ gssize res,
+ GError *io_error)
+{
+ IOOperationData *io_data = &iterator->io_data;
+ GError *error;
+
+ if (io_error != NULL)
+ {
+ if (error_is_cancel (io_error))
+ {
+ io_data->io_res = 0;
+ io_data->io_cancelled = TRUE;
+ }
+ else
+ {
+ error = NULL;
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), io_error->message);
+ async_iterator_done (iterator, error);
+ g_error_free (error);
+ return;
+ }
+ }
+ else if (res == 0 && io_data->io_size != 0)
+ {
+ error = NULL;
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error in stream protocol: %s"), _("End of stream"));
+ async_iterator_done (iterator, error);
+ g_error_free (error);
+ return;
+ }
+ else
+ {
+ io_data->io_res = res;
+ io_data->io_cancelled = FALSE;
+ }
+
+ async_iterate (iterator);
+}
+
+static void
+async_read_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ gssize count_read;
+ GError *error = NULL;
+
+ count_read = g_input_stream_read_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, count_read, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_skip_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ gssize count_skipped;
+ GError *error = NULL;
+
+ count_skipped = g_input_stream_skip_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, count_skipped, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_write_op_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GOutputStream *stream = G_OUTPUT_STREAM (source_object);
+ gssize bytes_written;
+ GError *error = NULL;
+
+ bytes_written = g_output_stream_write_finish (stream, res, &error);
+
+ async_op_handle ((AsyncIterator *)user_data, bytes_written, error);
+ if (error)
+ g_error_free (error);
+}
+
+static void
+async_iterate (AsyncIterator *iterator)
+{
+ IOOperationData *io_data = &iterator->io_data;
+ GDaemonFileOutputStream *file = iterator->file;
+ StateOp io_op;
+
+ io_data->cancelled =
+ g_cancellable_is_cancelled (iterator->cancellable);
+
+ io_op = iterator->iterator (file, io_data, iterator->iterator_data);
+
+ if (io_op == STATE_OP_DONE)
+ {
+ async_iterator_done (iterator, NULL);
+ return;
+ }
+
+ /* TODO: Handle allow_cancel... */
+
+ if (io_op == STATE_OP_READ)
+ {
+ g_input_stream_read_async (file->data_stream,
+ io_data->io_buffer, io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_read_op_callback, iterator);
+ }
+ else if (io_op == STATE_OP_SKIP)
+ {
+ g_input_stream_skip_async (file->data_stream,
+ io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_skip_op_callback, iterator);
+ }
+ else if (io_op == STATE_OP_WRITE)
+ {
+ g_output_stream_write_async (file->command_stream,
+ io_data->io_buffer, io_data->io_size,
+ iterator->io_priority,
+ io_data->io_allow_cancel ? iterator->cancellable : NULL,
+ async_write_op_callback, iterator);
+ }
+ else
+ g_assert_not_reached ();
+}
+
+static void
+run_async_state_machine (GDaemonFileOutputStream *file,
+ state_machine_iterator iterator_cb,
+ gpointer iterator_data,
+ int io_priority,
+ GAsyncReadyCallback callback,
+ gpointer data,
+ GCancellable *cancellable,
+ AsyncIteratorDone done_cb)
+{
+ AsyncIterator *iterator;
+
+ iterator = g_new0 (AsyncIterator, 1);
+ iterator->file = file;
+ iterator->iterator = iterator_cb;
+ iterator->iterator_data = iterator_data;
+ iterator->io_priority = io_priority;
+ iterator->cancellable = cancellable;
+ iterator->callback = callback;
+ iterator->callback_data = data;
+ iterator->done_cb = done_cb;
+
+ async_iterate (iterator);
+}
+
+static void
+async_write_done (GOutputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ GSimpleAsyncResult *simple;
+ WriteOperation *op;
+ gssize count_written;
+ GError *error;
+
+ op = op_data;
+
+ if (io_error)
+ {
+ count_written = -1;
+ error = io_error;
+ }
+ else
+ {
+ count_written = op->ret_val;
+ error = op->ret_error;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_output_stream_write_async);
+
+ g_simple_async_result_set_op_res_gssize (simple, count_written);
+
+ if (count_written == -1)
+ g_simple_async_result_set_from_error (simple, error);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op);
+}
+
+static void
+g_daemon_file_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ GDaemonFileOutputStream *file;
+ WriteOperation *op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ /* Limit for sanity and to avoid 32bit overflow */
+ if (count > MAX_WRITE_SIZE)
+ count = MAX_WRITE_SIZE;
+
+ op = g_new0 (WriteOperation, 1);
+ op->state = WRITE_STATE_INIT;
+ op->buffer = buffer;
+ op->buffer_size = count;
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_write_state_machine,
+ op,
+ io_priority,
+ callback, data,
+ cancellable,
+ async_write_done);
+}
+
+static gssize
+g_daemon_file_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gssize nwritten;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_output_stream_write_async);
+
+ nwritten = g_simple_async_result_get_op_res_gssize (simple);
+ return nwritten;
+}
+
+static void
+async_close_done (GOutputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ GDaemonFileOutputStream *file;
+ GSimpleAsyncResult *simple;
+ CloseOperation *op;
+ gboolean result;
+ GError *error;
+ GCancellable *cancellable = NULL; /* TODO: get cancellable */
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ op = op_data;
+
+ if (io_error)
+ {
+ result = FALSE;
+ error = io_error;
+ }
+ else
+ {
+ result = op->ret_val;
+ error = op->ret_error;
+ }
+
+ if (result)
+ result = g_output_stream_close (file->command_stream, cancellable, &error);
+ else
+ g_output_stream_close (file->command_stream, cancellable, NULL);
+
+ if (result)
+ result = g_input_stream_close (file->data_stream, cancellable, &error);
+ else
+ g_input_stream_close (file->data_stream, cancellable, NULL);
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_output_stream_close_async);
+
+ if (!result)
+ g_simple_async_result_set_from_error (simple, error);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op);
+}
+
+static void
+g_daemon_file_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ GDaemonFileOutputStream *file;
+ CloseOperation *op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ op = g_new0 (CloseOperation, 1);
+ op->state = CLOSE_STATE_INIT;
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_close_state_machine,
+ op, io_priority,
+ (GAsyncReadyCallback)callback, data,
+ cancellable,
+ (AsyncIteratorDone)async_close_done);
+}
+
+static gboolean
+g_daemon_file_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
+
+static void
+async_query_done (GOutputStream *stream,
+ gpointer op_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GError *io_error)
+{
+ GDaemonFileOutputStream *file;
+ GSimpleAsyncResult *simple;
+ QueryOperation *op;
+ GFileInfo *info;
+ GError *error;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ op = op_data;
+
+ if (io_error)
+ {
+ info = NULL;
+ error = io_error;
+ }
+ else
+ {
+ info = op->info;
+ error = op->ret_error;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ g_daemon_file_output_stream_query_info_async);
+
+ if (info == NULL)
+ g_simple_async_result_set_from_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple, info,
+ g_object_unref);
+
+ /* Complete immediately, not in idle, since we're already in a mainloop callout */
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ if (op->ret_error)
+ g_error_free (op->ret_error);
+ g_free (op->attributes);
+ g_free (op);
+}
+
+static void
+g_daemon_file_output_stream_query_info_async (GFileOutputStream *stream,
+ const char *attributes,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonFileOutputStream *file;
+ QueryOperation *op;
+
+ file = G_DAEMON_FILE_OUTPUT_STREAM (stream);
+
+ op = g_new0 (QueryOperation, 1);
+ op->state = QUERY_STATE_INIT;
+ if (attributes)
+ op->attributes = g_strdup (attributes);
+ else
+ op->attributes = g_strdup ("");
+
+ run_async_state_machine (file,
+ (state_machine_iterator)iterate_query_state_machine,
+ op, io_priority,
+ callback, user_data,
+ cancellable,
+ async_query_done);
+}
+
+static GFileInfo *
+g_daemon_file_output_stream_query_info_finish (GFileOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ GFileInfo *info;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_assert (g_simple_async_result_get_source_tag (simple) == g_daemon_file_output_stream_query_info_async);
+
+ info = g_simple_async_result_get_op_res_gpointer (simple);
+
+ return g_object_ref (info);
+
+}
diff --git a/trunk/client/gdaemonfileoutputstream.h b/trunk/client/gdaemonfileoutputstream.h
new file mode 100644
index 00000000..e609a48b
--- /dev/null
+++ b/trunk/client/gdaemonfileoutputstream.h
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_FILE_OUTPUT_STREAM_H__
+#define __G_DAEMON_FILE_OUTPUT_STREAM_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_FILE_OUTPUT_STREAM (g_daemon_file_output_stream_get_type ())
+#define G_DAEMON_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStream))
+#define G_DAEMON_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStreamClass))
+#define G_IS_DAEMON_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM))
+#define G_IS_DAEMON_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_FILE_OUTPUT_STREAM))
+#define G_DAEMON_FILE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DAEMON_FILE_OUTPUT_STREAM, GDaemonFileOutputStreamClass))
+
+typedef struct _GDaemonFileOutputStream GDaemonFileOutputStream;
+typedef struct _GDaemonFileOutputStreamClass GDaemonFileOutputStreamClass;
+
+struct _GDaemonFileOutputStreamClass
+{
+ GFileOutputStreamClass parent_class;
+};
+
+GType g_daemon_file_output_stream_get_type (void) G_GNUC_CONST;
+
+GFileOutputStream *g_daemon_file_output_stream_new (int fd,
+ gboolean can_seek,
+ goffset initial_offset);
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_FILE_OUTPUT_STREAM_H__ */
diff --git a/trunk/client/gdaemonmount.c b/trunk/client/gdaemonmount.c
new file mode 100644
index 00000000..5c41c026
--- /dev/null
+++ b/trunk/client/gdaemonmount.c
@@ -0,0 +1,278 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include "gdaemonvolumemonitor.h"
+#include "gdaemonmount.h"
+#include "gvfsdaemondbus.h"
+#include "gdaemonfile.h"
+#include "gvfsdaemonprotocol.h"
+#include "gdbusutils.h"
+
+/* Protects all fields of GDaemonMount that can change
+ which at this point is just foreign_volume */
+G_LOCK_DEFINE_STATIC(daemon_mount);
+
+struct _GDaemonMount {
+ GObject parent;
+
+ GMountInfo *mount_info;
+
+ GVolumeMonitor *volume_monitor;
+};
+
+static void g_daemon_mount_mount_iface_init (GMountIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GDaemonMount, g_daemon_mount, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
+ g_daemon_mount_mount_iface_init))
+
+static void
+g_daemon_mount_finalize (GObject *object)
+{
+ GDaemonMount *mount;
+
+ mount = G_DAEMON_MOUNT (object);
+
+ if (mount->volume_monitor != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor));
+
+ g_mount_info_unref (mount->mount_info);
+
+ if (G_OBJECT_CLASS (g_daemon_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_mount_class_init (GDaemonMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_mount_finalize;
+}
+
+static void
+g_daemon_mount_init (GDaemonMount *daemon_mount)
+{
+}
+
+GDaemonMount *
+g_daemon_mount_new (GMountInfo *mount_info,
+ GVolumeMonitor *volume_monitor)
+{
+ GDaemonMount *mount;
+
+ mount = g_object_new (G_TYPE_DAEMON_MOUNT, NULL);
+ mount->mount_info = g_mount_info_ref (mount_info);
+ mount->volume_monitor = volume_monitor;
+ g_object_set_data (G_OBJECT (mount), "g-stable-name", (gpointer) mount_info->stable_name);
+ if (mount->volume_monitor != NULL)
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(mount->volume_monitor));
+
+ return mount;
+}
+
+GMountInfo *
+g_daemon_mount_get_mount_info (GDaemonMount *mount)
+{
+ return mount->mount_info;
+}
+
+static GFile *
+g_daemon_mount_get_root (GMount *mount)
+{
+ GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+
+ return g_daemon_file_new (daemon_mount->mount_info->mount_spec, "/");
+}
+
+static GIcon *
+g_daemon_mount_get_icon (GMount *mount)
+{
+ GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+
+ return g_object_ref (daemon_mount->mount_info->icon);
+}
+
+static char *
+g_daemon_mount_get_name (GMount *mount)
+{
+ GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+
+ return g_strdup (daemon_mount->mount_info->display_name);
+}
+
+static char *
+g_daemon_mount_get_uuid (GMount *mount)
+{
+ return NULL;
+}
+
+static GVolume *
+g_daemon_mount_get_volume (GMount *mount)
+{
+ return NULL;
+}
+
+static GDrive *
+g_daemon_mount_get_drive (GMount *mount)
+{
+ return NULL;
+}
+
+static gboolean
+g_daemon_mount_can_unmount (GMount *mount)
+{
+ return TRUE;
+}
+
+static gboolean
+g_daemon_mount_can_eject (GMount *mount)
+{
+ return FALSE;
+}
+
+static void
+unmount_reply (DBusMessage *reply,
+ DBusConnection *connection,
+ GError *io_error,
+ gpointer _data)
+{
+ GSimpleAsyncResult *result = _data;
+
+ if (io_error != NULL)
+ g_simple_async_result_set_from_error (result, io_error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+static void
+g_daemon_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+ DBusMessage *message;
+ GMountInfo *mount_info;
+ GSimpleAsyncResult *res;
+ guint32 dbus_flags;
+
+ mount_info = daemon_mount->mount_info;
+
+ message =
+ dbus_message_new_method_call (mount_info->dbus_id,
+ mount_info->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_UNMOUNT);
+
+ dbus_flags = flags;
+ _g_dbus_message_append_args (message, DBUS_TYPE_UINT32, &dbus_flags, 0);
+
+ res = g_simple_async_result_new (G_OBJECT (mount),
+ callback, user_data,
+ g_daemon_mount_unmount);
+
+ _g_vfs_daemon_call_async (message,
+ unmount_reply, res,
+ cancellable);
+
+ dbus_message_unref (message);
+}
+
+static gboolean
+g_daemon_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+static char **
+g_daemon_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+ char **result;
+
+ G_LOCK (daemon_mount);
+ if (daemon_mount->mount_info->x_content_types != NULL &&
+ strlen (daemon_mount->mount_info->x_content_types) > 0)
+ result = g_strsplit (daemon_mount->mount_info->x_content_types, " ", 0);
+ else
+ result = g_new0 (char *, 1);
+ G_UNLOCK (daemon_mount);
+
+ return result;
+}
+
+static void
+g_daemon_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new (G_OBJECT (mount),
+ callback,
+ user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static char **
+g_daemon_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_daemon_mount_guess_content_type_sync (mount, FALSE, NULL, error);
+}
+
+static void
+g_daemon_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_daemon_mount_get_root;
+ iface->get_name = g_daemon_mount_get_name;
+ iface->get_icon = g_daemon_mount_get_icon;
+ iface->get_uuid = g_daemon_mount_get_uuid;
+ iface->get_volume = g_daemon_mount_get_volume;
+ iface->get_drive = g_daemon_mount_get_drive;
+ iface->can_unmount = g_daemon_mount_can_unmount;
+ iface->can_eject = g_daemon_mount_can_eject;
+ iface->unmount = g_daemon_mount_unmount;
+ iface->unmount_finish = g_daemon_mount_unmount_finish;
+ iface->guess_content_type = g_daemon_mount_guess_content_type;
+ iface->guess_content_type_finish = g_daemon_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_daemon_mount_guess_content_type_sync;
+}
diff --git a/trunk/client/gdaemonmount.h b/trunk/client/gdaemonmount.h
new file mode 100644
index 00000000..bf4ba099
--- /dev/null
+++ b/trunk/client/gdaemonmount.h
@@ -0,0 +1,57 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_MOUNT_H__
+#define __G_DAEMON_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "gdaemonvfs.h"
+#include "gdaemonvolumemonitor.h"
+#include "gmounttracker.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_MOUNT (g_daemon_mount_get_type ())
+#define G_DAEMON_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_MOUNT, GDaemonMount))
+#define G_DAEMON_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_MOUNT, GDaemonMountClass))
+#define G_IS_DAEMON_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_MOUNT))
+#define G_IS_DAEMON_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_MOUNT))
+
+typedef struct _GDaemonMountClass GDaemonMountClass;
+
+struct _GDaemonMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_daemon_mount_get_type (void) G_GNUC_CONST;
+
+GDaemonMount *g_daemon_mount_new (GMountInfo *mount_info,
+ GVolumeMonitor *volume_monitor);
+
+GMountInfo *g_daemon_mount_get_mount_info (GDaemonMount *mount);
+
+void g_daemon_mount_set_foreign_volume (GDaemonMount *mount, GVolume *foreign_volume);
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_MOUNT_H__ */
diff --git a/trunk/client/gdaemonvfs.c b/trunk/client/gdaemonvfs.c
new file mode 100644
index 00000000..c9f2cc97
--- /dev/null
+++ b/trunk/client/gdaemonvfs.c
@@ -0,0 +1,1152 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <dbus/dbus.h>
+#include "gdaemonvfs.h"
+#include "gvfsuriutils.h"
+#include "gdaemonfile.h"
+#include <gio/gio.h>
+#include <gvfsdaemonprotocol.h>
+#include <gmodule.h>
+#include "gvfsdaemondbus.h"
+#include "gdbusutils.h"
+#include "gmountspec.h"
+#include "gvfsurimapper.h"
+#include "gdaemonvolumemonitor.h"
+#include "gvfsicon.h"
+#include "gvfsiconloadable.h"
+#include <glib/gi18n-lib.h>
+
+typedef struct {
+ char *type;
+ char *scheme;
+ char **scheme_aliases;
+ int default_port;
+ gboolean host_is_inet;
+} MountableInfo;
+
+struct _GDaemonVfs
+{
+ GVfs parent;
+
+ DBusConnection *async_bus;
+
+ GVfs *wrapped_vfs;
+ GList *mount_cache;
+
+ GFile *fuse_root;
+
+ GHashTable *from_uri_hash;
+ GHashTable *to_uri_hash;
+
+ MountableInfo **mountable_info;
+ char **supported_uri_schemes;
+};
+
+struct _GDaemonVfsClass
+{
+ GVfsClass parent_class;
+};
+
+G_DEFINE_DYNAMIC_TYPE (GDaemonVfs, g_daemon_vfs, G_TYPE_VFS)
+
+static GDaemonVfs *the_vfs = NULL;
+
+G_LOCK_DEFINE_STATIC(mount_cache);
+
+
+static void fill_mountable_info (GDaemonVfs *vfs);
+
+static void
+g_daemon_vfs_finalize (GObject *object)
+{
+ GDaemonVfs *vfs;
+
+ vfs = G_DAEMON_VFS (object);
+
+ if (vfs->from_uri_hash)
+ g_hash_table_destroy (vfs->from_uri_hash);
+
+ if (vfs->to_uri_hash)
+ g_hash_table_destroy (vfs->to_uri_hash);
+
+ g_strfreev (vfs->supported_uri_schemes);
+
+ if (vfs->async_bus)
+ {
+ dbus_connection_close (vfs->async_bus);
+ dbus_connection_unref (vfs->async_bus);
+ }
+
+ if (vfs->wrapped_vfs)
+ g_object_unref (vfs->wrapped_vfs);
+
+ /* must chain up */
+ G_OBJECT_CLASS (g_daemon_vfs_parent_class)->finalize (object);
+}
+
+static MountableInfo *
+get_mountable_info_for_scheme (GDaemonVfs *vfs,
+ const char *scheme)
+{
+ MountableInfo *info;
+ int i, j;
+
+ if (vfs->mountable_info == NULL)
+ return NULL;
+
+ for (i = 0; vfs->mountable_info[i] != NULL; i++)
+ {
+ info = vfs->mountable_info[i];
+
+ if (info->scheme != NULL && strcmp (info->scheme, scheme) == 0)
+ return info;
+
+ if (info->scheme_aliases != NULL)
+ {
+ for (j = 0; info->scheme_aliases[j] != NULL; j++)
+ {
+ if (strcmp (info->scheme_aliases[j], scheme) == 0)
+ return info;
+ }
+ }
+
+ }
+
+ return NULL;
+}
+
+static MountableInfo *
+get_mountable_info_for_type (GDaemonVfs *vfs,
+ const char *type)
+{
+ MountableInfo *info;
+ int i;
+
+ if (vfs->mountable_info == NULL)
+ return NULL;
+
+ for (i = 0; vfs->mountable_info[i] != NULL; i++)
+ {
+ info = vfs->mountable_info[i];
+
+ if (strcmp (info->type, type) == 0)
+ return info;
+ }
+
+ return NULL;
+}
+
+static void
+str_tolower_inplace (char *str)
+{
+ char *p = str;
+
+ while (*p != 0)
+ {
+ *p = g_ascii_tolower (*p);
+ p++;
+ }
+
+}
+
+static gboolean
+get_mountspec_from_uri (GDaemonVfs *vfs,
+ const char *uri,
+ GMountSpec **spec_out,
+ char **path_out)
+{
+ GMountSpec *spec;
+ char *path;
+ GVfsUriMapper *mapper;
+ char *scheme;
+ GVfsUriMountInfo *info;
+
+ scheme = g_uri_parse_scheme (uri);
+ if (scheme == NULL)
+ return FALSE;
+
+ /* convert the scheme to lower case since g_uri_parse_scheme
+ * doesn't do that and we compare with g_str_equal */
+ str_tolower_inplace (scheme);
+
+ spec = NULL;
+ path = NULL;
+
+ mapper = g_hash_table_lookup (vfs->from_uri_hash, scheme);
+
+ if (mapper)
+ {
+ info = g_vfs_uri_mapper_from_uri (mapper, uri);
+ if (info != NULL)
+ {
+ spec = g_mount_spec_new_from_data (info->keys, NULL);
+ path = info->path;
+ /* We took over ownership of info parts, custom free: */
+ g_free (info);
+ }
+ }
+
+ if (spec == NULL)
+ {
+ GDecodedUri *decoded;
+ MountableInfo *mountable;
+ char *type;
+ int l;
+
+ decoded = g_vfs_decode_uri (uri);
+ if (decoded)
+ {
+ mountable = get_mountable_info_for_scheme (vfs, decoded->scheme);
+
+ if (mountable)
+ type = mountable->type;
+ else
+ type = decoded->scheme;
+
+ spec = g_mount_spec_new (type);
+
+ if (decoded->host && *decoded->host)
+ {
+ if (mountable && mountable->host_is_inet)
+ {
+ /* Convert hostname to lower case */
+ str_tolower_inplace (decoded->host);
+
+ /* Remove brackets aroung ipv6 addresses */
+ l = strlen (decoded->host);
+ if (decoded->host[0] == '[' &&
+ decoded->host[l - 1] == ']')
+ g_mount_spec_set_with_len (spec, "host", decoded->host+1, l - 2);
+ else
+ g_mount_spec_set (spec, "host", decoded->host);
+ }
+ else
+ g_mount_spec_set (spec, "host", decoded->host);
+ }
+
+ if (decoded->userinfo && *decoded->userinfo)
+ g_mount_spec_set (spec, "user", decoded->userinfo);
+
+ if (decoded->port != -1 &&
+ (mountable == NULL ||
+ mountable->default_port == 0 ||
+ mountable->default_port != decoded->port))
+ {
+ char *port = g_strdup_printf ("%d", decoded->port);
+ g_mount_spec_set (spec, "port", port);
+ g_free (port);
+ }
+
+ if (decoded->query && *decoded->query)
+ g_mount_spec_set (spec, "query", decoded->query);
+ if (decoded->fragment && *decoded->fragment)
+ g_mount_spec_set (spec, "fragment", decoded->fragment);
+
+ path = g_strdup (decoded->path);
+
+ g_vfs_decoded_uri_free (decoded);
+ }
+ }
+
+ g_free (scheme);
+
+ if (spec == NULL)
+ return FALSE;
+
+ *spec_out = spec;
+ *path_out = path;
+
+ return TRUE;
+}
+
+static void
+g_daemon_vfs_init (GDaemonVfs *vfs)
+{
+ GType *mappers;
+ guint n_mappers;
+ const char * const *schemes, * const *mount_types;
+ GVfsUriMapper *mapper;
+ GList *modules;
+ char *file;
+ int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ vfs->async_bus = dbus_bus_get_private (DBUS_BUS_SESSION, NULL);
+
+ if (vfs->async_bus == NULL)
+ return; /* Not supported, return here and return false in vfs_is_active() */
+
+ g_assert (the_vfs == NULL);
+ the_vfs = vfs;
+
+ if (g_thread_supported ())
+ dbus_threads_init_default ();
+
+ /* We disable SIGPIPE globally. This is sort of bad
+ for s library to do since its a global resource.
+ However, without this there is no way to be able
+ to handle mount daemons dying without client apps
+ crashing, which is much worse.
+
+ I blame Unix, there really should be a portable
+ way to do this on all unixes, but there isn't,
+ even for somewhat modern ones like solaris.
+ */
+ signal (SIGPIPE, SIG_IGN);
+
+ fill_mountable_info (vfs);
+
+ vfs->wrapped_vfs = g_vfs_get_local ();
+
+ file = g_build_filename (g_get_home_dir(), ".gvfs", NULL);
+ vfs->fuse_root = g_vfs_get_file_for_path (vfs->wrapped_vfs, file);
+ g_free (file);
+
+ dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE);
+
+ _g_dbus_connection_integrate_with_main (vfs->async_bus);
+
+ modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR);
+
+ vfs->from_uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ vfs->to_uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ mappers = g_type_children (G_VFS_TYPE_URI_MAPPER, &n_mappers);
+
+ for (i = 0; i < n_mappers; i++)
+ {
+ int j;
+ mapper = g_object_new (mappers[i], NULL);
+
+ schemes = g_vfs_uri_mapper_get_handled_schemes (mapper);
+
+ for (j = 0; schemes != NULL && schemes[j] != NULL; j++)
+ g_hash_table_insert (vfs->from_uri_hash, (char *)schemes[j], mapper);
+
+ mount_types = g_vfs_uri_mapper_get_handled_mount_types (mapper);
+ for (j = 0; mount_types != NULL && mount_types[j] != NULL; j++)
+ g_hash_table_insert (vfs->to_uri_hash, (char *)mount_types[j], mapper);
+ }
+
+ /* The above should have ref:ed the modules anyway */
+ g_list_foreach (modules, (GFunc)g_type_module_unuse, NULL);
+ g_list_free (modules);
+ g_free (mappers);
+}
+
+GDaemonVfs *
+g_daemon_vfs_new (void)
+{
+ return g_object_new (G_TYPE_DAEMON_VFS, NULL);
+}
+
+/* This unrefs file if its changed */
+static GFile *
+convert_fuse_path (GVfs *vfs,
+ GFile *file)
+{
+ GFile *fuse_root;
+ char *fuse_path, *mount_path;
+ GMountInfo *mount_info;
+
+ fuse_root = ((GDaemonVfs *)vfs)->fuse_root;
+ if (g_file_has_prefix (file, fuse_root))
+ {
+ fuse_path = g_file_get_path (file);
+ mount_info = _g_daemon_vfs_get_mount_info_by_fuse_sync (fuse_path, &mount_path);
+ g_free (fuse_path);
+ if (mount_info)
+ {
+ g_object_unref (file);
+ /* TODO: Do we need to look at the prefix of the mount_spec? */
+ file = g_daemon_file_new (mount_info->mount_spec, mount_path);
+ g_free (mount_path);
+ g_mount_info_unref (mount_info);
+ }
+ }
+ return file;
+}
+
+static GFile *
+g_daemon_vfs_get_file_for_path (GVfs *vfs,
+ const char *path)
+{
+ GFile *file;
+
+ file = g_vfs_get_file_for_path (G_DAEMON_VFS (vfs)->wrapped_vfs, path);
+ file = convert_fuse_path (vfs, file);
+ return file;
+}
+
+static GFile *
+g_daemon_vfs_get_file_for_uri (GVfs *vfs,
+ const char *uri)
+{
+ GDaemonVfs *daemon_vfs;
+ GFile *file;
+ GMountSpec *spec;
+ char *path;
+
+ daemon_vfs = G_DAEMON_VFS (vfs);
+
+ if (g_ascii_strncasecmp (uri, "file:", 5) == 0)
+ {
+ path = g_filename_from_uri (uri, NULL, NULL);
+
+ if (path == NULL)
+ /* Dummy file */
+ return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri);
+
+ file = g_daemon_vfs_get_file_for_path (vfs, path);
+ g_free (path);
+ return file;
+ }
+
+ if (get_mountspec_from_uri (daemon_vfs, uri, &spec, &path))
+ {
+ file = g_daemon_file_new (spec, path);
+ g_mount_spec_unref (spec);
+ g_free (path);
+ return file;
+ }
+
+ /* Dummy file */
+ return g_vfs_get_file_for_uri (G_DAEMON_VFS (vfs)->wrapped_vfs, uri);
+}
+
+GMountSpec *
+_g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec,
+ const char *path,
+ const char *new_path)
+{
+ const char *type;
+ GVfsUriMapper *mapper;
+ GMountSpec *new_spec;
+
+ type = g_mount_spec_get_type (spec);
+
+ if (type == NULL)
+ return g_mount_spec_ref (spec);
+
+ new_spec = NULL;
+ mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
+ if (mapper)
+ {
+ GVfsUriMountInfo info, *new_info;
+ info.keys = spec->items;
+ info.path = (char *)path;
+ new_info = g_vfs_uri_mapper_get_mount_info_for_path (mapper, &info, new_path);
+ if (new_info != NULL)
+ {
+ new_spec = g_mount_spec_new_from_data (new_info->keys, NULL);
+ /* We took over ownership of parts of new_info, custom free: */
+ g_free (new_info->path);
+ g_free (new_info);
+ }
+ }
+
+ if (new_spec == NULL)
+ new_spec = g_mount_spec_ref (spec);
+
+ return new_spec;
+}
+
+char *
+_g_daemon_vfs_get_uri_for_mountspec (GMountSpec *spec,
+ char *path,
+ gboolean allow_utf8)
+{
+ char *uri;
+ const char *type;
+ GVfsUriMapper *mapper;
+
+ type = g_mount_spec_get_type (spec);
+ if (type == NULL)
+ {
+ GString *string = g_string_new ("unknown://");
+ if (path)
+ g_string_append_uri_escaped (string,
+ path,
+ "!$&'()*+,;=:@/",
+ allow_utf8);
+
+ return g_string_free (string, FALSE);
+ }
+
+ uri = NULL;
+ mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
+ if (mapper)
+ {
+ GVfsUriMountInfo info;
+ info.keys = spec->items;
+ info.path = path;
+ uri = g_vfs_uri_mapper_to_uri (mapper, &info, allow_utf8);
+ }
+
+ if (uri == NULL)
+ {
+ GDecodedUri decoded;
+ MountableInfo *mountable;
+ const char *port;
+ gboolean free_host;
+
+ memset (&decoded, 0, sizeof (decoded));
+ decoded.port = -1;
+
+ mountable = get_mountable_info_for_type (the_vfs, type);
+
+ if (mountable)
+ decoded.scheme = mountable->scheme;
+ else
+ decoded.scheme = (char *)type;
+ decoded.host = (char *)g_mount_spec_get (spec, "host");
+ free_host = FALSE;
+ if (mountable && mountable->host_is_inet && decoded.host != NULL && strchr (decoded.host, ':') != NULL)
+ {
+ free_host = TRUE;
+ decoded.host = g_strconcat ("[", decoded.host, "]", NULL);
+ }
+
+ decoded.userinfo = (char *)g_mount_spec_get (spec, "user");
+ port = g_mount_spec_get (spec, "port");
+ if (port != NULL)
+ decoded.port = atoi (port);
+
+ if (path == NULL)
+ decoded.path = "/";
+ else
+ decoded.path = path;
+
+ decoded.query = (char *)g_mount_spec_get (spec, "query");
+ decoded.fragment = (char *)g_mount_spec_get (spec, "fragment");
+
+ uri = g_vfs_encode_uri (&decoded, FALSE);
+
+ if (free_host)
+ g_free (decoded.host);
+ }
+
+ return uri;
+}
+
+const char *
+_g_daemon_vfs_mountspec_get_uri_scheme (GMountSpec *spec)
+{
+ const char *type, *scheme;
+ GVfsUriMapper *mapper;
+ MountableInfo *mountable;
+
+ type = g_mount_spec_get_type (spec);
+ mapper = g_hash_table_lookup (the_vfs->to_uri_hash, type);
+
+ scheme = NULL;
+ if (mapper)
+ {
+ GVfsUriMountInfo info;
+
+ info.keys = spec->items;
+ info.path = "/";
+
+ scheme = g_vfs_uri_mapper_to_uri_scheme (mapper, &info);
+ }
+
+ if (scheme == NULL)
+ {
+ mountable = get_mountable_info_for_type (the_vfs, type);
+ if (mountable)
+ scheme = mountable->scheme;
+ else
+ scheme = type;
+ }
+
+ return scheme;
+}
+
+static int
+find_string (GPtrArray *array, const char *find_me)
+{
+ int i;
+
+ g_return_val_if_fail (find_me != NULL, -1);
+
+ for (i = 0; i < array->len; ++i)
+ {
+ if (strcmp (g_ptr_array_index (array, i), find_me) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
+static void
+fill_mountable_info (GDaemonVfs *vfs)
+{
+ DBusMessage *message, *reply;
+ DBusError error;
+ DBusMessageIter iter, array_iter, struct_iter;
+ MountableInfo *info;
+ GPtrArray *infos, *uri_schemes;
+ gint i, count;
+
+ message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO);
+
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_set_auto_start (message, TRUE);
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (vfs->async_bus,
+ message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ &error);
+ dbus_message_unref (message);
+
+ if (dbus_error_is_set (&error))
+ {
+ dbus_error_free (&error);
+ return;
+ }
+
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_iter_init (reply, &iter);
+
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ infos = g_ptr_array_new ();
+ uri_schemes = g_ptr_array_new ();
+ count = 0;
+ do
+ {
+ char *type, *scheme, **scheme_aliases;
+ int scheme_aliases_len;
+ gint32 default_port;
+ dbus_bool_t host_is_inet;
+
+ if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_STRUCT)
+ break;
+
+ dbus_message_iter_recurse (&array_iter, &struct_iter);
+
+ if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &scheme,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &scheme_aliases, &scheme_aliases_len,
+ DBUS_TYPE_INT32, &default_port,
+ DBUS_TYPE_BOOLEAN, &host_is_inet,
+ 0))
+ break;
+
+ info = g_new0 (MountableInfo, 1);
+ info->type = g_strdup (type);
+ if (*scheme != 0)
+ {
+ info->scheme = g_strdup (scheme);
+ if (find_string (uri_schemes, scheme) == -1)
+ g_ptr_array_add (uri_schemes, g_strdup (scheme));
+ }
+
+ if (scheme_aliases_len > 0)
+ {
+ info->scheme_aliases = g_new (char *, scheme_aliases_len + 1);
+ for (i = 0; i < scheme_aliases_len; i++)
+ {
+ info->scheme_aliases[i] = g_strdup (scheme_aliases[i]);
+ if (find_string (uri_schemes, scheme_aliases[i]) == -1)
+ g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i]));
+ }
+ info->scheme_aliases[scheme_aliases_len] = NULL;
+ }
+
+ info->default_port = default_port;
+ info->host_is_inet = host_is_inet;
+
+ g_ptr_array_add (infos, info);
+
+ g_strfreev (scheme_aliases);
+ }
+ while (dbus_message_iter_next (&array_iter));
+
+ dbus_message_unref (reply);
+
+ g_ptr_array_add (uri_schemes, NULL);
+ g_ptr_array_add (infos, NULL);
+ vfs->mountable_info = (MountableInfo **)g_ptr_array_free (infos, FALSE);
+ vfs->supported_uri_schemes = (char **)g_ptr_array_free (uri_schemes, FALSE);
+}
+
+
+static const gchar * const *
+g_daemon_vfs_get_supported_uri_schemes (GVfs *vfs)
+{
+ return (const gchar * const *) G_DAEMON_VFS (vfs)->supported_uri_schemes;
+}
+
+static GMountInfo *
+lookup_mount_info_in_cache_locked (GMountSpec *spec,
+ const char *path)
+{
+ GMountInfo *info;
+ GList *l;
+
+ info = NULL;
+ for (l = the_vfs->mount_cache; l != NULL; l = l->next)
+ {
+ GMountInfo *mount_info = l->data;
+
+ if (g_mount_spec_match_with_path (mount_info->mount_spec, spec, path))
+ {
+ info = g_mount_info_ref (mount_info);
+ break;
+ }
+ }
+
+ return info;
+}
+
+static GMountInfo *
+lookup_mount_info_in_cache (GMountSpec *spec,
+ const char *path)
+{
+ GMountInfo *info;
+
+ G_LOCK (mount_cache);
+ info = lookup_mount_info_in_cache_locked (spec, path);
+ G_UNLOCK (mount_cache);
+
+ return info;
+}
+
+static GMountInfo *
+lookup_mount_info_by_fuse_path_in_cache (const char *fuse_path,
+ char **mount_path)
+{
+ GMountInfo *info;
+ GList *l;
+
+ G_LOCK (mount_cache);
+ info = NULL;
+ for (l = the_vfs->mount_cache; l != NULL; l = l->next)
+ {
+ GMountInfo *mount_info = l->data;
+
+ if (mount_info->fuse_mountpoint != NULL &&
+ g_str_has_prefix (fuse_path, mount_info->fuse_mountpoint))
+ {
+ int len = strlen (mount_info->fuse_mountpoint);
+ if (fuse_path[len] == 0 ||
+ fuse_path[len] == '/')
+ {
+ if (fuse_path[len] == 0)
+ *mount_path = g_strdup ("/");
+ else
+ *mount_path = g_strdup (fuse_path + len);
+ info = g_mount_info_ref (mount_info);
+ break;
+ }
+ }
+ }
+ G_UNLOCK (mount_cache);
+
+ return info;
+}
+
+
+void
+_g_daemon_vfs_invalidate_dbus_id (const char *dbus_id)
+{
+ GList *l, *next;
+
+ G_LOCK (mount_cache);
+ for (l = the_vfs->mount_cache; l != NULL; l = next)
+ {
+ GMountInfo *mount_info = l->data;
+ next = l->next;
+
+ if (strcmp (mount_info->dbus_id, dbus_id) == 0)
+ {
+ the_vfs->mount_cache = g_list_delete_link (the_vfs->mount_cache, l);
+ g_mount_info_unref (mount_info);
+ }
+ }
+
+ G_UNLOCK (mount_cache);
+}
+
+
+static GMountInfo *
+handler_lookup_mount_reply (DBusMessage *reply,
+ GError **error)
+{
+ DBusError derror;
+ GMountInfo *info;
+ DBusMessageIter iter;
+ GList *l;
+ gboolean in_cache;
+
+
+ if (_g_error_from_message (reply, error))
+ return NULL;
+
+ dbus_error_init (&derror);
+ dbus_message_iter_init (reply, &iter);
+
+ info = g_mount_info_from_dbus (&iter);
+ if (info == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error while getting mount info: %s"),
+ "Invalid reply");
+ return NULL;
+ }
+
+ G_LOCK (mount_cache);
+
+ in_cache = FALSE;
+ /* Already in cache from other thread? */
+ for (l = the_vfs->mount_cache; l != NULL; l = l->next)
+ {
+ GMountInfo *cached_info = l->data;
+
+ if (g_mount_info_equal (info, cached_info))
+ {
+ in_cache = TRUE;
+ g_mount_info_unref (info);
+ info = g_mount_info_ref (cached_info);
+ break;
+ }
+ }
+
+ /* No, lets add it to the cache */
+ if (!in_cache)
+ the_vfs->mount_cache = g_list_prepend (the_vfs->mount_cache, g_mount_info_ref (info));
+
+ G_UNLOCK (mount_cache);
+
+ return info;
+}
+
+typedef struct {
+ GMountInfoLookupCallback callback;
+ gpointer user_data;
+} GetMountInfoData;
+
+static void
+async_get_mount_info_response (DBusMessage *reply,
+ GError *io_error,
+ void *_data)
+{
+ GetMountInfoData *data = _data;
+ GMountInfo *info;
+ GError *error;
+
+ if (reply == NULL)
+ data->callback (NULL, data->user_data, io_error);
+ else
+ {
+ error = NULL;
+ info = handler_lookup_mount_reply (reply, &error);
+
+ data->callback (info, data->user_data, error);
+
+ if (info)
+ g_mount_info_unref (info);
+
+ if (error)
+ g_error_free (error);
+ }
+
+ g_free (data);
+}
+
+void
+_g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
+ const char *path,
+ GMountInfoLookupCallback callback,
+ gpointer user_data)
+{
+ GMountInfo *info;
+ GetMountInfoData *data;
+ DBusMessage *message;
+ DBusMessageIter iter;
+
+ info = lookup_mount_info_in_cache (spec, path);
+
+ if (info != NULL)
+ {
+ callback (info, user_data, NULL);
+ g_mount_info_unref (info);
+ return;
+ }
+
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
+ dbus_message_set_auto_start (message, TRUE);
+
+ dbus_message_iter_init_append (message, &iter);
+ g_mount_spec_to_dbus_with_path (&iter, spec, path);
+
+ data = g_new0 (GetMountInfoData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ _g_dbus_connection_call_async (the_vfs->async_bus, message, G_VFS_DBUS_TIMEOUT_MSECS,
+ async_get_mount_info_response,
+ data);
+
+ dbus_message_unref (message);
+}
+
+
+GMountInfo *
+_g_daemon_vfs_get_mount_info_sync (GMountSpec *spec,
+ const char *path,
+ GError **error)
+{
+ GMountInfo *info;
+ DBusConnection *conn;
+ DBusMessage *message, *reply;
+ DBusMessageIter iter;
+ DBusError derror;
+
+ info = lookup_mount_info_in_cache (spec, path);
+
+ if (info != NULL)
+ return info;
+
+ conn = _g_dbus_connection_get_sync (NULL, error);
+ if (conn == NULL)
+ return NULL;
+
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
+ dbus_message_set_auto_start (message, TRUE);
+
+ dbus_message_iter_init_append (message, &iter);
+ g_mount_spec_to_dbus_with_path (&iter, spec, path);
+
+ dbus_error_init (&derror);
+ reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
+ dbus_message_unref (message);
+
+ if (!reply)
+ {
+ _g_error_from_dbus (&derror, error);
+ dbus_error_free (&derror);
+ return NULL;
+ }
+
+ info = handler_lookup_mount_reply (reply, error);
+
+ dbus_message_unref (reply);
+
+ return info;
+}
+
+GMountInfo *
+_g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
+ char **mount_path)
+{
+ GMountInfo *info;
+ DBusConnection *conn;
+ DBusMessage *message, *reply;
+ DBusMessageIter iter;
+ DBusError derror;
+ int len;
+
+ info = lookup_mount_info_by_fuse_path_in_cache (fuse_path,
+ mount_path);
+ if (info != NULL)
+ return info;
+
+ conn = _g_dbus_connection_get_sync (NULL, NULL);
+ if (conn == NULL)
+ return NULL;
+
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH);
+ dbus_message_set_auto_start (message, TRUE);
+
+ dbus_message_iter_init_append (message, &iter);
+ _g_dbus_message_iter_append_cstring (&iter, fuse_path);
+
+ dbus_error_init (&derror);
+ reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
+ dbus_message_unref (message);
+ if (!reply)
+ {
+ dbus_error_free (&derror);
+ return NULL;
+ }
+
+ info = handler_lookup_mount_reply (reply, NULL);
+ dbus_message_unref (reply);
+
+ if (info)
+ {
+ if (info->fuse_mountpoint)
+ {
+ len = strlen (info->fuse_mountpoint);
+ if (fuse_path[len] == 0)
+ *mount_path = g_strdup ("/");
+ else
+ *mount_path = g_strdup (fuse_path + len);
+ }
+ else
+ {
+ /* This could happen if we race with the gvfs fuse mount
+ * at startup of gvfsd... */
+ g_mount_info_unref (info);
+ info = NULL;
+ }
+ }
+
+
+ return info;
+}
+
+static GFile *
+g_daemon_vfs_parse_name (GVfs *vfs,
+ const char *parse_name)
+{
+ GFile *file;
+
+ if (g_path_is_absolute (parse_name) ||
+ *parse_name == '~')
+ {
+ file = g_vfs_parse_name (G_DAEMON_VFS (vfs)->wrapped_vfs, parse_name);
+ file = convert_fuse_path (vfs, file);
+ }
+ else
+ {
+ file = g_daemon_vfs_get_file_for_uri (vfs, parse_name);
+ }
+
+ return file;
+}
+
+DBusConnection *
+_g_daemon_vfs_get_async_bus (void)
+{
+ return the_vfs->async_bus;
+}
+
+static gboolean
+g_daemon_vfs_is_active (GVfs *vfs)
+{
+ GDaemonVfs *daemon_vfs = G_DAEMON_VFS (vfs);
+ return daemon_vfs->async_bus != NULL;
+}
+
+static void
+g_daemon_vfs_class_finalize (GDaemonVfsClass *klass)
+{
+}
+
+static void
+g_daemon_vfs_class_init (GDaemonVfsClass *class)
+{
+ GObjectClass *object_class;
+ GVfsClass *vfs_class;
+
+ object_class = (GObjectClass *) class;
+
+ g_daemon_vfs_parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = g_daemon_vfs_finalize;
+
+ vfs_class = G_VFS_CLASS (class);
+
+ vfs_class->is_active = g_daemon_vfs_is_active;
+ vfs_class->get_file_for_path = g_daemon_vfs_get_file_for_path;
+ vfs_class->get_file_for_uri = g_daemon_vfs_get_file_for_uri;
+ vfs_class->get_supported_uri_schemes = g_daemon_vfs_get_supported_uri_schemes;
+ vfs_class->parse_name = g_daemon_vfs_parse_name;
+}
+
+/* Module API */
+
+void g_vfs_uri_mapper_smb_register (GIOModule *module);
+void g_vfs_uri_mapper_http_register (GIOModule *module);
+void g_vfs_uri_mapper_sftp_register (GIOModule *module);
+
+void
+g_io_module_load (GIOModule *module)
+{
+ /* This is so that system daemons can use gio
+ * without spawning private dbus instances.
+ * See bug 526454.
+ */
+ if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
+ return;
+
+ /* Make this module resident so that we ground the common
+ * library. If that is unloaded we could get into all kinds
+ * of strange situations. This is safe to do even if we loaded
+ * some other common-using module first as all modules are loaded
+ * before any are freed.
+ */
+ g_type_module_use (G_TYPE_MODULE (module));
+
+ g_daemon_vfs_register_type (G_TYPE_MODULE (module));
+ g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module));
+
+ /* We implement GLoadableIcon only on client side.
+ see comment in common/giconvfs.c */
+ _g_vfs_icon_add_loadable_interface ();
+
+ g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME,
+ G_TYPE_DAEMON_VFS,
+ "gvfs",
+ 10);
+
+ g_vfs_uri_mapper_register (module);
+ g_vfs_uri_mapper_smb_register (module);
+ g_vfs_uri_mapper_http_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/trunk/client/gdaemonvfs.h b/trunk/client/gdaemonvfs.h
new file mode 100644
index 00000000..fae0904c
--- /dev/null
+++ b/trunk/client/gdaemonvfs.h
@@ -0,0 +1,75 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_VFS_H__
+#define __G_DAEMON_VFS_H__
+
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+#include "gmountspec.h"
+#include "gmounttracker.h"
+#include "gvfsuriutils.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_VFS (g_daemon_vfs_get_type ())
+#define G_DAEMON_VFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DAEMON_VFS, GDaemonVfs))
+#define G_DAEMON_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_DAEMON_VFS, GDaemonVfsClass))
+#define G_IS_DAEMON_VFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DAEMON_VFS))
+#define G_IS_DAEMON_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_DAEMON_VFS))
+#define G_DAEMON_VFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_DAEMON_VFS, GDaemonVfsClass))
+
+typedef struct _GDaemonVfs GDaemonVfs;
+typedef struct _GDaemonVfsClass GDaemonVfsClass;
+
+typedef void (*GMountInfoLookupCallback) (GMountInfo *mount_info,
+ gpointer data,
+ GError *error);
+
+GType g_daemon_vfs_get_type (void);
+
+GDaemonVfs *g_daemon_vfs_new (void);
+
+char * _g_daemon_vfs_get_uri_for_mountspec (GMountSpec *spec,
+ char *path,
+ gboolean allow_utf8);
+const char * _g_daemon_vfs_mountspec_get_uri_scheme (GMountSpec *spec);
+void _g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
+ const char *path,
+ GMountInfoLookupCallback callback,
+ gpointer user_data);
+GMountInfo * _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec,
+ const char *path,
+ GError **error);
+GMountInfo * _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
+ char **mount_path);
+GMountSpec * _g_daemon_vfs_get_mount_spec_for_path (GMountSpec *spec,
+ const char *path,
+ const char *new_path);
+void _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id);
+DBusConnection *_g_daemon_vfs_get_async_bus (void);
+
+
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_VFS_H__ */
diff --git a/trunk/client/gdaemonvolumemonitor.c b/trunk/client/gdaemonvolumemonitor.c
new file mode 100644
index 00000000..2ca21130
--- /dev/null
+++ b/trunk/client/gdaemonvolumemonitor.c
@@ -0,0 +1,321 @@
+
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include "gdaemonvolumemonitor.h"
+#include "gdaemonmount.h"
+#include "gdaemonvfs.h"
+#include "gmounttracker.h"
+
+G_LOCK_DEFINE_STATIC(daemon_vm);
+
+static GDaemonVolumeMonitor *_the_daemon_volume_monitor;
+
+struct _GDaemonVolumeMonitor {
+ GVolumeMonitor parent;
+
+ GMountTracker *mount_tracker;
+ GList *mounts;
+};
+
+G_DEFINE_DYNAMIC_TYPE (GDaemonVolumeMonitor, g_daemon_volume_monitor, G_TYPE_VOLUME_MONITOR)
+
+static GList *
+get_mounts (GVolumeMonitor *volume_monitor)
+{
+ GDaemonVolumeMonitor *monitor;
+ GList *l;
+
+ G_LOCK (daemon_vm);
+
+ monitor = G_DAEMON_VOLUME_MONITOR (volume_monitor);
+
+ l = g_list_copy (monitor->mounts);
+ g_list_foreach (l, (GFunc)g_object_ref, NULL);
+
+ G_UNLOCK (daemon_vm);
+
+ return l;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+ /* TODO: Can daemon mounts have volumes? */
+ return NULL;
+}
+
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
+{
+ /* TODO: Can daemon mounts have drives? */
+ return NULL;
+}
+
+static GVolume *
+get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ return NULL;
+}
+
+static GMount *
+get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ return NULL;
+}
+
+static GDaemonMount *
+find_mount_by_mount_info (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
+{
+ GDaemonMount *found_mount = NULL;
+ GList *l;
+
+ for (l = daemon_monitor->mounts; l; l = g_list_next (l))
+ {
+ GDaemonMount *existing_mount = l->data;
+ GMountInfo *existing_mount_info;
+
+ existing_mount_info = g_daemon_mount_get_mount_info (existing_mount);
+ if (g_mount_info_equal (mount_info, existing_mount_info))
+ {
+ found_mount = existing_mount;
+ break;
+ }
+ }
+
+ return found_mount;
+}
+
+GDaemonMount *
+g_daemon_volume_monitor_find_mount_by_mount_info (GMountInfo *mount_info)
+{
+ GDaemonMount *daemon_mount;
+
+ G_LOCK (daemon_vm);
+
+ daemon_mount = NULL;
+ if (_the_daemon_volume_monitor != NULL)
+ {
+ daemon_mount = find_mount_by_mount_info (_the_daemon_volume_monitor, mount_info);
+
+ if (daemon_mount != NULL)
+ g_object_ref (daemon_mount);
+ }
+
+ G_UNLOCK (daemon_vm);
+
+ return daemon_mount;
+}
+
+static void
+mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
+{
+ GDaemonMount *mount;
+
+ G_LOCK (daemon_vm);
+
+ mount = find_mount_by_mount_info (daemon_monitor, mount_info);
+ if (mount)
+ {
+ g_warning (G_STRLOC ": Mount was added twice!");
+
+ G_UNLOCK (daemon_vm);
+ return;
+ }
+
+ if (mount_info->user_visible)
+ {
+ mount = g_daemon_mount_new (mount_info, G_VOLUME_MONITOR (daemon_monitor));
+ daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
+
+ /* Ref for the signal emission, other ref is owned by volume monitor */
+ g_object_ref (mount);
+ }
+
+ G_UNLOCK (daemon_vm);
+
+ if (mount)
+ {
+ /* Emit signal outside lock */
+ g_signal_emit_by_name (daemon_monitor, "mount_added", mount);
+ g_object_unref (mount);
+ }
+}
+
+static void
+mount_removed (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info)
+{
+ GDaemonMount *mount;
+
+ G_LOCK (daemon_vm);
+
+ mount = find_mount_by_mount_info (daemon_monitor, mount_info);
+ if (!mount)
+ {
+ if (mount_info->user_visible)
+ g_warning (G_STRLOC ": An unknown mount was removed!");
+
+ G_UNLOCK (daemon_vm);
+ return;
+ }
+
+ daemon_monitor->mounts = g_list_remove (daemon_monitor->mounts, mount);
+
+ G_UNLOCK (daemon_vm);
+
+ g_signal_emit_by_name (daemon_monitor, "mount_removed", mount);
+ g_signal_emit_by_name (mount, "unmounted");
+
+ g_object_unref (mount);
+}
+
+static void
+g_daemon_volume_monitor_init (GDaemonVolumeMonitor *daemon_monitor)
+{
+ GList *mounts, *l;
+ GDaemonMount *mount;
+ GMountInfo *info;
+
+ _the_daemon_volume_monitor = daemon_monitor;
+
+ daemon_monitor->mount_tracker = g_mount_tracker_new (_g_daemon_vfs_get_async_bus ());
+
+ g_signal_connect_swapped (daemon_monitor->mount_tracker, "mounted",
+ (GCallback) mount_added, daemon_monitor);
+ g_signal_connect_swapped (daemon_monitor->mount_tracker, "unmounted",
+ (GCallback) mount_removed, daemon_monitor);
+
+ /* Initialize with current list */
+ mounts = g_mount_tracker_list_mounts (daemon_monitor->mount_tracker);
+
+ for (l = mounts; l != NULL; l = l->next) {
+ info = l->data;
+ if (info->user_visible)
+ {
+ mount = g_daemon_mount_new (info, G_VOLUME_MONITOR (daemon_monitor));
+ daemon_monitor->mounts = g_list_prepend (daemon_monitor->mounts, mount);
+ }
+
+ g_mount_info_unref (info);
+ }
+
+ g_list_free (mounts);
+}
+
+static void
+g_daemon_volume_monitor_finalize (GObject *object)
+{
+ GDaemonVolumeMonitor *monitor;
+
+ monitor = G_DAEMON_VOLUME_MONITOR (object);
+
+ g_signal_handlers_disconnect_by_func (monitor->mount_tracker, mount_added, monitor);
+ g_signal_handlers_disconnect_by_func (monitor->mount_tracker, mount_removed, monitor);
+
+ g_object_unref (monitor->mount_tracker);
+
+ g_list_foreach (monitor->mounts, (GFunc)g_object_unref, NULL);
+ g_list_free (monitor->mounts);
+
+ if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) (object);
+}
+
+static void
+g_daemon_volume_monitor_dispose (GObject *object)
+{
+ GDaemonVolumeMonitor *monitor;
+
+ monitor = G_DAEMON_VOLUME_MONITOR (object);
+
+ G_LOCK (daemon_vm);
+ _the_daemon_volume_monitor = NULL;
+ G_UNLOCK (daemon_vm);
+
+ if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose)
+ (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose) (object);
+}
+
+static void
+g_daemon_volume_monitor_class_finalize (GDaemonVolumeMonitorClass *klass)
+{
+}
+
+static gboolean
+is_supported (void)
+{
+ GVfs *vfs;
+ gboolean res;
+
+ res = FALSE;
+
+ /* Don't do anything if the default vfs is not DAEMON_VFS */
+ vfs = g_vfs_get_default ();
+
+ if (vfs != NULL && G_IS_DAEMON_VFS (vfs))
+ res = TRUE;
+
+ return res;
+}
+
+static void
+g_daemon_volume_monitor_class_init (GDaemonVolumeMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+
+ gobject_class->finalize = g_daemon_volume_monitor_finalize;
+ gobject_class->dispose = g_daemon_volume_monitor_dispose;
+
+ monitor_class->is_supported = is_supported;
+ monitor_class->get_mounts = get_mounts;
+ monitor_class->get_volumes = get_volumes;
+ monitor_class->get_connected_drives = get_connected_drives;
+ monitor_class->get_volume_for_uuid = get_volume_for_uuid;
+ monitor_class->get_mount_for_uuid = get_mount_for_uuid;
+}
+
+GVolumeMonitor *
+g_daemon_volume_monitor_new (void)
+{
+ GDaemonVolumeMonitor *monitor;
+
+ monitor = g_object_new (G_TYPE_DAEMON_VOLUME_MONITOR, NULL);
+
+ return G_VOLUME_MONITOR (monitor);
+}
+
+void
+g_daemon_volume_monitor_register_types (GTypeModule *module)
+{
+ g_daemon_volume_monitor_register_type (G_TYPE_MODULE (module));
+ g_io_extension_point_implement (G_VOLUME_MONITOR_EXTENSION_POINT_NAME,
+ G_TYPE_DAEMON_VOLUME_MONITOR,
+ "gvfs",
+ 0);
+}
diff --git a/trunk/client/gdaemonvolumemonitor.h b/trunk/client/gdaemonvolumemonitor.h
new file mode 100644
index 00000000..4019ca35
--- /dev/null
+++ b/trunk/client/gdaemonvolumemonitor.h
@@ -0,0 +1,60 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DAEMON_VOLUME_MONITOR_H__
+#define __G_DAEMON_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "gmounttracker.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DAEMON_VOLUME_MONITOR (g_daemon_volume_monitor_get_type ())
+#define G_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitor))
+#define G_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DAEMON_VOLUME_MONITOR, GDaemonVolumeMonitorClass))
+#define G_IS_DAEMON_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DAEMON_VOLUME_MONITOR))
+#define G_IS_DAEMON_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DAEMON_VOLUME_MONITOR))
+
+typedef struct _GDaemonVolumeMonitor GDaemonVolumeMonitor;
+typedef struct _GDaemonVolumeMonitorClass GDaemonVolumeMonitorClass;
+
+/* Forward definitions */
+typedef struct _GDaemonMount GDaemonMount;
+typedef struct _GDaemonVolume GDaemonVolume;
+typedef struct _GDaemonDrive GDaemonDrive;
+
+struct _GDaemonVolumeMonitorClass {
+ GVolumeMonitorClass parent_class;
+
+};
+
+GType g_daemon_volume_monitor_get_type (void) G_GNUC_CONST;
+void g_daemon_volume_monitor_register_types (GTypeModule *type_module);
+
+GVolumeMonitor *g_daemon_volume_monitor_new (void);
+
+GDaemonMount *g_daemon_volume_monitor_find_mount_by_mount_info (GMountInfo *mount_info);
+
+G_END_DECLS
+
+#endif /* __G_DAEMON_VOLUME_MONITOR_H__ */
diff --git a/trunk/client/gvfsdaemondbus.c b/trunk/client/gvfsdaemondbus.c
new file mode 100644
index 00000000..c3df2cf6
--- /dev/null
+++ b/trunk/client/gvfsdaemondbus.c
@@ -0,0 +1,1023 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <gio/gio.h>
+#include "gvfsdaemondbus.h"
+#include <gvfsdaemonprotocol.h>
+#include <gdaemonvfs.h>
+#include "gdbusutils.h"
+#include "gsysutils.h"
+
+/* Extra vfs-specific data for DBusConnections */
+typedef struct {
+ int extra_fd;
+ int extra_fd_count;
+ char *async_dbus_id;
+
+ /* Only used for async connections */
+ GHashTable *outstanding_fds;
+ GSource *extra_fd_source;
+} VfsConnectionData;
+
+static gint32 vfs_data_slot = -1;
+static GOnce once_init_dbus = G_ONCE_INIT;
+
+static GStaticPrivate local_connections = G_STATIC_PRIVATE_INIT;
+
+/* dbus id -> async connection */
+static GHashTable *async_map = NULL;
+G_LOCK_DEFINE_STATIC(async_map);
+
+/* dbus object path -> dbus message filter */
+static GHashTable *obj_path_map = NULL;
+G_LOCK_DEFINE_STATIC(obj_path_map);
+
+static void setup_async_fd_receive (VfsConnectionData *connection_data);
+static void invalidate_local_connection (const char *dbus_id,
+ GError **error);
+
+
+GQuark
+_g_vfs_error_quark (void)
+{
+ return g_quark_from_static_string ("g-vfs-error-quark");
+}
+
+static gpointer
+vfs_dbus_init (gpointer arg)
+{
+ if (!dbus_connection_allocate_data_slot (&vfs_data_slot))
+ g_error ("Unable to allocate data slot");
+
+ return NULL;
+}
+
+/**************************************************************************
+ * message filters for vfs dbus connections *
+ *************************************************************************/
+
+typedef struct {
+ DBusHandleMessageFunction callback;
+ GObject *data;
+} PathMapEntry;
+
+void
+_g_dbus_register_vfs_filter (const char *obj_path,
+ DBusHandleMessageFunction callback,
+ GObject *data)
+{
+ PathMapEntry * entry;
+
+ G_LOCK (obj_path_map);
+
+ if (obj_path_map == NULL)
+ obj_path_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ entry = g_new (PathMapEntry,1 );
+ entry->callback = callback;
+ entry->data = data;
+
+ g_hash_table_insert (obj_path_map, g_strdup (obj_path), entry);
+
+ G_UNLOCK (obj_path_map);
+}
+
+void
+_g_dbus_unregister_vfs_filter (const char *obj_path)
+{
+ G_LOCK (obj_path_map);
+
+ if (obj_path_map)
+ g_hash_table_remove (obj_path_map, obj_path);
+
+ G_UNLOCK (obj_path_map);
+}
+
+static DBusHandlerResult
+vfs_connection_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ PathMapEntry *entry;
+ DBusHandlerResult res;
+ DBusHandleMessageFunction callback;
+ GObject *data;
+ VfsConnectionData *connection_data;
+ const char *path;
+
+ callback = NULL;
+ data = NULL;
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected"))
+ {
+ connection_data = dbus_connection_get_data (connection, vfs_data_slot);
+ if (connection_data->async_dbus_id)
+ {
+ _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id);
+ G_LOCK (async_map);
+ g_hash_table_remove (async_map, connection_data->async_dbus_id);
+ G_UNLOCK (async_map);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ path = dbus_message_get_path (message);
+ G_LOCK (obj_path_map);
+ if (obj_path_map && path)
+ {
+ entry = g_hash_table_lookup (obj_path_map,
+ path);
+
+ if (entry)
+ {
+ callback = entry->callback;
+ data = g_object_ref (entry->data);
+ }
+ }
+ G_UNLOCK (obj_path_map);
+
+ res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (callback)
+ {
+ res = callback (connection, message, data);
+ g_object_unref (data);
+ }
+
+ return res;
+}
+
+static void
+connection_data_free (gpointer p)
+{
+ VfsConnectionData *data = p;
+
+ if (data->extra_fd != -1)
+ close (data->extra_fd);
+
+ if (data->extra_fd_source)
+ {
+ g_source_destroy (data->extra_fd_source);
+ g_source_unref (data->extra_fd_source);
+ }
+
+ if (data->outstanding_fds)
+ g_hash_table_destroy (data->outstanding_fds);
+
+ g_free (data->async_dbus_id);
+
+ g_free (data);
+}
+
+static void
+vfs_connection_setup (DBusConnection *connection,
+ int extra_fd,
+ gboolean async)
+{
+ VfsConnectionData *connection_data;
+
+ connection_data = g_new0 (VfsConnectionData, 1);
+ connection_data->extra_fd = extra_fd;
+ connection_data->extra_fd_count = 0;
+
+ if (async)
+ setup_async_fd_receive (connection_data);
+
+ if (!dbus_connection_set_data (connection, vfs_data_slot, connection_data, connection_data_free))
+ _g_dbus_oom ();
+
+ if (!dbus_connection_add_filter (connection, vfs_connection_filter, NULL, NULL))
+ _g_dbus_oom ();
+}
+
+/**************************************************************************
+ * Functions to get fds from vfs dbus connections *
+ *************************************************************************/
+
+typedef struct {
+ int fd;
+ GetFdAsyncCallback callback;
+ gpointer callback_data;
+} OutstandingFD;
+
+static void
+outstanding_fd_free (OutstandingFD *outstanding)
+{
+ if (outstanding->fd != -1)
+ close (outstanding->fd);
+
+ g_free (outstanding);
+}
+
+static void
+async_connection_accept_new_fd (VfsConnectionData *data,
+ GIOCondition condition,
+ int fd)
+{
+ int new_fd;
+ int fd_id;
+ OutstandingFD *outstanding_fd;
+
+ if (condition & G_IO_HUP)
+ {
+ close (data->extra_fd);
+ data->extra_fd = -1;
+ g_source_destroy (data->extra_fd_source);
+ g_source_unref (data->extra_fd_source);
+ data->extra_fd_source = NULL;
+ return;
+ }
+
+ fd_id = data->extra_fd_count;
+ new_fd = _g_socket_receive_fd (data->extra_fd);
+ if (new_fd != -1)
+ {
+ data->extra_fd_count++;
+
+ outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id));
+
+ if (outstanding_fd)
+ {
+ outstanding_fd->callback (new_fd, outstanding_fd->callback_data);
+ g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id));
+ }
+ else
+ {
+ outstanding_fd = g_new0 (OutstandingFD, 1);
+ outstanding_fd->fd = new_fd;
+ outstanding_fd->callback = NULL;
+ outstanding_fd->callback_data = NULL;
+ g_hash_table_insert (data->outstanding_fds,
+ GINT_TO_POINTER (fd_id),
+ outstanding_fd);
+ }
+ }
+}
+
+static void
+setup_async_fd_receive (VfsConnectionData *connection_data)
+{
+ connection_data->outstanding_fds =
+ g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify)outstanding_fd_free);
+
+
+ connection_data->extra_fd_source =
+ __g_fd_source_new (connection_data->extra_fd, G_IO_IN|G_IO_ERR, NULL);
+ g_source_set_callback (connection_data->extra_fd_source,
+ (GSourceFunc)async_connection_accept_new_fd,
+ connection_data, NULL);
+ g_source_attach (connection_data->extra_fd_source, NULL);
+}
+
+int
+_g_dbus_connection_get_fd_sync (DBusConnection *connection,
+ int fd_id)
+{
+ VfsConnectionData *data;
+ int fd;
+
+ data = dbus_connection_get_data (connection, vfs_data_slot);
+ g_assert (data != NULL);
+
+ /* I don't think we can get reorders here, can we?
+ * Its a sync per-thread connection after all
+ */
+ g_assert (fd_id == data->extra_fd_count);
+
+ fd = _g_socket_receive_fd (data->extra_fd);
+ if (fd != -1)
+ data->extra_fd_count++;
+
+ return fd;
+}
+
+void
+_g_dbus_connection_get_fd_async (DBusConnection *connection,
+ int fd_id,
+ GetFdAsyncCallback callback,
+ gpointer callback_data)
+{
+ VfsConnectionData *data;
+ OutstandingFD *outstanding_fd;
+ int fd;
+
+ data = dbus_connection_get_data (connection, vfs_data_slot);
+ g_assert (data != NULL);
+
+ outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id));
+
+ if (outstanding_fd)
+ {
+ fd = outstanding_fd->fd;
+ outstanding_fd->fd = -1;
+ g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id));
+ callback (fd, callback_data);
+ }
+ else
+ {
+ outstanding_fd = g_new0 (OutstandingFD, 1);
+ outstanding_fd->fd = -1;
+ outstanding_fd->callback = callback;
+ outstanding_fd->callback_data = callback_data;
+ g_hash_table_insert (data->outstanding_fds,
+ GINT_TO_POINTER (fd_id),
+ outstanding_fd);
+ }
+}
+
+/*******************************************************************
+ * Caching of async connections *
+ *******************************************************************/
+
+
+static DBusConnection *
+get_connection_for_async (const char *dbus_id)
+{
+ DBusConnection *connection;
+
+ connection = NULL;
+ G_LOCK (async_map);
+ if (async_map != NULL)
+ connection = g_hash_table_lookup (async_map, dbus_id);
+ if (connection)
+ dbus_connection_ref (connection);
+ G_UNLOCK (async_map);
+
+ return connection;
+}
+
+static void
+close_and_unref_connection (void *data)
+{
+ DBusConnection *connection = data;
+
+ dbus_connection_close (connection);
+ dbus_connection_unref (connection);
+}
+
+static void
+set_connection_for_async (DBusConnection *connection, const char *dbus_id)
+{
+ VfsConnectionData *data;
+
+ G_LOCK (async_map);
+ data = dbus_connection_get_data (connection, vfs_data_slot);
+ data->async_dbus_id = g_strdup (dbus_id);
+
+ if (async_map == NULL)
+ async_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, close_and_unref_connection);
+
+ g_hash_table_insert (async_map, g_strdup (dbus_id), connection);
+ dbus_connection_ref (connection);
+ G_UNLOCK (async_map);
+}
+
+/**************************************************************************
+ * Asynchronous daemon calls *
+ *************************************************************************/
+
+typedef struct {
+ const char *dbus_id;
+
+ DBusMessage *message;
+ DBusConnection *connection;
+ GCancellable *cancellable;
+
+ GVfsAsyncDBusCallback callback;
+ gpointer callback_data;
+
+ GError *io_error;
+ gulong cancelled_tag;
+} AsyncDBusCall;
+
+static void
+async_call_finish (AsyncDBusCall *async_call,
+ DBusMessage *reply)
+{
+ if (async_call->callback)
+ async_call->callback (reply, async_call->connection,
+ async_call->io_error,
+ async_call->callback_data);
+
+ if (async_call->connection)
+ dbus_connection_unref (async_call->connection);
+ dbus_message_unref (async_call->message);
+ if (async_call->cancellable)
+ g_object_unref (async_call->cancellable);
+ if (async_call->io_error)
+ g_error_free (async_call->io_error);
+ g_free (async_call);
+}
+
+static void
+async_dbus_response (DBusMessage *reply,
+ GError *error,
+ gpointer data)
+{
+ AsyncDBusCall *async_call = data;
+
+ if (async_call->cancelled_tag)
+ g_signal_handler_disconnect (async_call->cancellable,
+ async_call->cancelled_tag);
+
+ if (reply == NULL)
+ async_call->io_error = g_error_copy (error);
+
+ async_call_finish (async_call, reply);
+}
+
+typedef struct {
+ DBusConnection *connection;
+ dbus_uint32_t serial;
+} AsyncCallCancelData;
+
+static void
+async_call_cancel_data_free (gpointer _data)
+{
+ AsyncCallCancelData *data = _data;
+
+ dbus_connection_unref (data->connection);
+ g_free (data);
+}
+
+/* Might be called on another thread */
+static void
+async_call_cancelled_cb (GCancellable *cancellable,
+ gpointer _data)
+{
+ AsyncCallCancelData *data = _data;
+ DBusMessage *cancel_message;
+
+ /* Send cancellation message, this just queues it, sending
+ * will happen in mainloop */
+ cancel_message = dbus_message_new_method_call (NULL,
+ G_VFS_DBUS_DAEMON_PATH,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_CANCEL);
+ if (cancel_message != NULL)
+ {
+ if (dbus_message_append_args (cancel_message,
+ DBUS_TYPE_UINT32, &data->serial,
+ DBUS_TYPE_INVALID))
+ dbus_connection_send (data->connection,
+ cancel_message, NULL);
+ dbus_message_unref (cancel_message);
+ }
+}
+
+static void
+async_call_send (AsyncDBusCall *async_call)
+{
+ AsyncCallCancelData *cancel_data;
+
+ if (async_call->cancellable)
+ {
+ cancel_data = g_new0 (AsyncCallCancelData, 1);
+ cancel_data->connection = dbus_connection_ref (async_call->connection);
+ cancel_data->serial = dbus_message_get_serial (async_call->message);
+ async_call->cancelled_tag =
+ g_signal_connect_data (async_call->cancellable, "cancelled",
+ (GCallback)async_call_cancelled_cb,
+ cancel_data,
+ (GClosureNotify)async_call_cancel_data_free,
+ 0);
+ }
+
+ _g_dbus_connection_call_async (async_call->connection,
+ async_call->message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ async_dbus_response,
+ async_call);
+}
+
+static void
+async_get_connection_response (DBusMessage *reply,
+ GError *error,
+ void *data)
+{
+ AsyncDBusCall *async_call = data;
+ DBusError derror;
+ char *address1, *address2;
+ int extra_fd;
+ DBusConnection *connection, *existing_connection;
+
+ if (reply == NULL)
+ {
+ async_call->io_error = g_error_copy (error);
+ async_call_finish (async_call, NULL);
+ return;
+ }
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (reply, &derror,
+ DBUS_TYPE_STRING, &address1,
+ DBUS_TYPE_STRING, &address2,
+ DBUS_TYPE_INVALID))
+ {
+ _g_error_from_dbus (&derror, &async_call->io_error);
+ dbus_error_free (&derror);
+ async_call_finish (async_call, NULL);
+ return;
+ }
+
+ /* I don't know of any way to do an async connect */
+ error = NULL;
+ extra_fd = _g_socket_connect (address2, &error);
+ if (extra_fd == -1)
+ {
+ g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error connecting to daemon: %s"), error->message);
+ g_error_free (error);
+ async_call_finish (async_call, NULL);
+ return;
+ }
+
+ /* Unfortunately dbus doesn't have an async open */
+ dbus_error_init (&derror);
+ connection = dbus_connection_open_private (address1, &derror);
+ if (!connection)
+ {
+ close (extra_fd);
+ dbus_message_unref (reply);
+
+ g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ derror.message);
+ dbus_error_free (&derror);
+ async_call_finish (async_call, NULL);
+ return;
+ }
+
+ vfs_connection_setup (connection, extra_fd, TRUE);
+
+ /* Maybe we already had a connection? This happens if we requested
+ * the same owner several times in parallel.
+ * If so, just drop this connection and use that.
+ */
+
+ existing_connection = get_connection_for_async (async_call->dbus_id);
+ if (existing_connection != NULL)
+ {
+ async_call->connection = existing_connection;
+ dbus_connection_close (connection);
+ dbus_connection_unref (connection);
+ }
+ else
+ {
+ _g_dbus_connection_integrate_with_main (connection);
+ set_connection_for_async (connection, async_call->dbus_id);
+ async_call->connection = connection;
+ }
+
+ /* Maybe we were canceled while setting up connection, then
+ * avoid doing the operation */
+ if (g_cancellable_set_error_if_cancelled (async_call->cancellable, &async_call->io_error))
+ {
+ async_call_finish (async_call, NULL);
+ return;
+ }
+
+ async_call_send (async_call);
+}
+
+static void
+open_connection_async (AsyncDBusCall *async_call)
+{
+ DBusMessage *get_connection_message;
+
+ get_connection_message = dbus_message_new_method_call (async_call->dbus_id,
+ G_VFS_DBUS_DAEMON_PATH,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_GET_CONNECTION);
+
+ if (get_connection_message == NULL)
+ _g_dbus_oom ();
+
+
+ _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (),
+ get_connection_message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ async_get_connection_response,
+ async_call);
+
+ dbus_message_unref (get_connection_message);
+}
+
+void
+_g_vfs_daemon_call_async (DBusMessage *message,
+ GVfsAsyncDBusCallback callback,
+ gpointer callback_data,
+ GCancellable *cancellable)
+{
+ AsyncDBusCall *async_call;
+
+ g_once (&once_init_dbus, vfs_dbus_init, NULL);
+
+ async_call = g_new0 (AsyncDBusCall, 1);
+ async_call->dbus_id = dbus_message_get_destination (message);
+ async_call->message = dbus_message_ref (message);
+ if (cancellable)
+ async_call->cancellable = g_object_ref (cancellable);
+ async_call->callback = callback;
+ async_call->callback_data = callback_data;
+
+ async_call->connection = get_connection_for_async (async_call->dbus_id);
+ if (async_call->connection == NULL)
+ open_connection_async (async_call);
+ else
+ async_call_send (async_call);
+}
+
+/**************************************************************************
+ * Synchronous daemon calls *
+ *************************************************************************/
+
+DBusMessage *
+_g_vfs_daemon_call_sync (DBusMessage *message,
+ DBusConnection **connection_out,
+ const char *callback_obj_path,
+ DBusObjectPathMessageFunction callback,
+ gpointer callback_user_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ DBusError derror;
+ DBusMessage *reply;
+ DBusPendingCall *pending;
+ int dbus_fd;
+ int cancel_fd;
+ gboolean sent_cancel;
+ DBusMessage *cancel_message;
+ dbus_uint32_t serial;
+ gboolean handle_callbacks;
+ const char *dbus_id = dbus_message_get_destination (message);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return NULL;
+
+ connection = _g_dbus_connection_get_sync (dbus_id, error);
+ if (connection == NULL)
+ return NULL;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return NULL;
+
+ handle_callbacks = FALSE;
+ if (callback_obj_path != NULL && callback != NULL)
+ {
+ struct DBusObjectPathVTable vtable = { NULL, callback };
+ handle_callbacks = dbus_connection_register_object_path (connection,
+ callback_obj_path,
+ &vtable,
+ callback_user_data);
+ }
+
+ reply = NULL;
+ cancel_fd = g_cancellable_get_fd (cancellable);
+ if (cancel_fd != -1 || handle_callbacks)
+ {
+ if (!dbus_connection_send_with_reply (connection, message,
+ &pending,
+ G_VFS_DBUS_TIMEOUT_MSECS))
+ _g_dbus_oom ();
+
+ if (pending == NULL ||
+ !dbus_connection_get_is_connected (connection))
+ {
+ if (pending)
+ dbus_pending_call_unref (pending);
+ invalidate_local_connection (dbus_id, error);
+ goto out;
+ }
+
+ /* Make sure the message is sent */
+ dbus_connection_flush (connection);
+
+ if (!dbus_connection_get_unix_fd (connection, &dbus_fd))
+ {
+ dbus_pending_call_unref (pending);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ "No fd");
+ goto out;
+ }
+
+ sent_cancel = (cancel_fd == -1);
+ while (!dbus_pending_call_get_completed (pending))
+ {
+ GPollFD poll_fds[2];
+ int poll_ret;
+
+ do
+ {
+ poll_fds[0].events = G_IO_IN;
+ poll_fds[0].fd = dbus_fd;
+ poll_fds[1].events = G_IO_IN;
+ poll_fds[1].fd = cancel_fd;
+ poll_ret = g_poll (poll_fds, sent_cancel?1:2, -1);
+ }
+ while (poll_ret == -1 && errno == EINTR);
+
+ if (poll_ret == -1)
+ {
+ dbus_pending_call_unref (pending);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ "poll error");
+ goto out;
+ }
+
+ if (!sent_cancel && g_cancellable_is_cancelled (cancellable))
+ {
+ sent_cancel = TRUE;
+ serial = dbus_message_get_serial (message);
+ cancel_message =
+ dbus_message_new_method_call (NULL,
+ G_VFS_DBUS_DAEMON_PATH,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_CANCEL);
+ if (cancel_message != NULL)
+ {
+ if (dbus_message_append_args (cancel_message,
+ DBUS_TYPE_UINT32, &serial,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_connection_send (connection, cancel_message, NULL);
+ dbus_connection_flush (connection);
+ }
+
+ dbus_message_unref (cancel_message);
+ }
+ }
+
+ if (poll_fds[0].revents != 0)
+ {
+ dbus_connection_read_write (connection,
+ G_VFS_DBUS_TIMEOUT_MSECS);
+
+ while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS)
+ ;
+ }
+ }
+
+ reply = dbus_pending_call_steal_reply (pending);
+ dbus_pending_call_unref (pending);
+ }
+ else
+ {
+ dbus_error_init (&derror);
+ reply = dbus_connection_send_with_reply_and_block (connection, message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ &derror);
+ if (!reply)
+ {
+ if (dbus_error_has_name (&derror, DBUS_ERROR_NO_REPLY) &&
+ !dbus_connection_get_is_connected (connection))
+ {
+ /* The mount for this connection died, we invalidate
+ * the caches, and then caller needs to retry.
+ */
+
+ invalidate_local_connection (dbus_id, error);
+ }
+ else
+ _g_error_from_dbus (&derror, error);
+ dbus_error_free (&derror);
+ goto out;
+ }
+ }
+
+ if (connection_out)
+ *connection_out = connection;
+
+ out:
+
+ if (handle_callbacks)
+ dbus_connection_unregister_object_path (connection, callback_obj_path);
+
+ if (reply != NULL && _g_error_from_message (reply, error))
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+
+ return reply;
+}
+
+/*************************************************************************
+ * get per-thread synchronous dbus connections *
+ *************************************************************************/
+
+typedef struct {
+ GHashTable *connections;
+ DBusConnection *session_bus;
+} ThreadLocalConnections;
+
+static void
+free_mount_connection (DBusConnection *conn)
+{
+ dbus_connection_close (conn);
+ dbus_connection_unref (conn);
+}
+
+static void
+free_local_connections (ThreadLocalConnections *local)
+{
+ g_hash_table_destroy (local->connections);
+ if (local->session_bus)
+ free_mount_connection (local->session_bus);
+ g_free (local);
+}
+
+static void
+invalidate_local_connection (const char *dbus_id,
+ GError **error)
+{
+ ThreadLocalConnections *local;
+
+ _g_daemon_vfs_invalidate_dbus_id (dbus_id);
+
+ local = g_static_private_get (&local_connections);
+ if (local)
+ g_hash_table_remove (local->connections, dbus_id);
+
+ g_set_error_literal (error,
+ G_VFS_ERROR,
+ G_VFS_ERROR_RETRY,
+ "Cache invalid, retry (internally handled)");
+}
+
+DBusConnection *
+_g_dbus_connection_get_sync (const char *dbus_id,
+ GError **error)
+{
+ DBusConnection *bus;
+ ThreadLocalConnections *local;
+ GError *local_error;
+ DBusConnection *connection;
+ DBusMessage *message, *reply;
+ DBusError derror;
+ char *address1, *address2;
+ int extra_fd;
+
+ g_once (&once_init_dbus, vfs_dbus_init, NULL);
+
+ local = g_static_private_get (&local_connections);
+ if (local == NULL)
+ {
+ local = g_new0 (ThreadLocalConnections, 1);
+ local->connections = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify)free_mount_connection);
+ g_static_private_set (&local_connections, local, (GDestroyNotify)free_local_connections);
+ }
+
+ if (dbus_id == NULL)
+ {
+ /* Session bus */
+
+ if (local->session_bus)
+ {
+ if (dbus_connection_get_is_connected (local->session_bus))
+ return local->session_bus;
+
+ /* Session bus was disconnected, re-connect */
+ local->session_bus = NULL;
+ dbus_connection_unref (local->session_bus);
+ }
+ }
+ else
+ {
+ /* Mount daemon connection */
+
+ connection = g_hash_table_lookup (local->connections, dbus_id);
+ if (connection != NULL)
+ {
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ /* The mount for this connection died, we invalidate
+ * the caches, and then caller needs to retry.
+ */
+
+ invalidate_local_connection (dbus_id, error);
+ return NULL;
+ }
+
+ return connection;
+ }
+ }
+
+ dbus_error_init (&derror);
+
+ if (local->session_bus == NULL)
+ {
+ bus = dbus_bus_get_private (DBUS_BUS_SESSION, &derror);
+ if (bus == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Couldn't get main dbus connection: %s",
+ derror.message);
+ dbus_error_free (&derror);
+ return NULL;
+ }
+
+ local->session_bus = bus;
+
+ if (dbus_id == NULL)
+ return bus; /* We actually wanted the session bus, so done */
+ }
+
+ message = dbus_message_new_method_call (dbus_id,
+ G_VFS_DBUS_DAEMON_PATH,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_GET_CONNECTION);
+ reply = dbus_connection_send_with_reply_and_block (local->session_bus, message, -1,
+ &derror);
+ dbus_message_unref (message);
+
+ if (!reply)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ derror.message);
+ dbus_error_free (&derror);
+ return NULL;
+ }
+
+ if (_g_error_from_message (reply, error))
+ return NULL;
+
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_STRING, &address1,
+ DBUS_TYPE_STRING, &address2,
+ DBUS_TYPE_INVALID);
+
+ local_error = NULL;
+ extra_fd = _g_socket_connect (address2, &local_error);
+ if (extra_fd == -1)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error connecting to daemon: %s"), local_error->message);
+ g_error_free (local_error);
+ dbus_message_unref (reply);
+ return NULL;
+ }
+
+ dbus_error_init (&derror);
+ connection = dbus_connection_open_private (address1, &derror);
+ if (!connection)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ derror.message);
+ close (extra_fd);
+ dbus_message_unref (reply);
+ dbus_error_free (&derror);
+ return NULL;
+ }
+ dbus_message_unref (reply);
+
+ vfs_connection_setup (connection, extra_fd, FALSE);
+
+ g_hash_table_insert (local->connections, g_strdup (dbus_id), connection);
+
+ return connection;
+}
diff --git a/trunk/client/gvfsdaemondbus.h b/trunk/client/gvfsdaemondbus.h
new file mode 100644
index 00000000..7a132cdc
--- /dev/null
+++ b/trunk/client/gvfsdaemondbus.h
@@ -0,0 +1,80 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_DAEMON_DBUS_H__
+#define __G_VFS_DAEMON_DBUS_H__
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* Used for internal errors */
+GQuark _g_vfs_error_quark (void);
+#define G_VFS_ERROR _g_vfs_error_quark()
+
+typedef enum
+{
+ G_VFS_ERROR_RETRY
+} GVfsError;
+
+
+typedef void (*GVfsAsyncDBusCallback) (DBusMessage *reply,
+ DBusConnection *connection,
+ GError *io_error,
+ gpointer callback_data);
+typedef void (*GetFdAsyncCallback) (int fd,
+ gpointer callback_data);
+
+void _g_dbus_register_vfs_filter (const char *obj_path,
+ DBusHandleMessageFunction callback,
+ GObject *data);
+void _g_dbus_unregister_vfs_filter (const char *obj_path);
+GList * _g_dbus_bus_list_names_with_prefix_sync (DBusConnection *connection,
+ const char *prefix,
+ DBusError *error);
+DBusConnection *_g_dbus_connection_get_sync (const char *dbus_id,
+ GError **error);
+int _g_dbus_connection_get_fd_sync (DBusConnection *conn,
+ int fd_id);
+void _g_dbus_connection_get_fd_async (DBusConnection *connection,
+ int fd_id,
+ GetFdAsyncCallback callback,
+ gpointer callback_data);
+void _g_vfs_daemon_call_async (DBusMessage *message,
+ GVfsAsyncDBusCallback callback,
+ gpointer callback_data,
+ GCancellable *cancellable);
+DBusMessage * _g_vfs_daemon_call_sync (DBusMessage *message,
+ DBusConnection **connection_out,
+ const char *callback_obj_path,
+ DBusObjectPathMessageFunction callback,
+ gpointer callback_user_data,
+ GCancellable *cancellable,
+ GError **error);
+GFileInfo * _g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DAEMON_DBUS_H__ */
diff --git a/trunk/client/gvfsfusedaemon.c b/trunk/client/gvfsfusedaemon.c
new file mode 100644
index 00000000..9071776f
--- /dev/null
+++ b/trunk/client/gvfsfusedaemon.c
@@ -0,0 +1,2324 @@
+/* gvfsfusedaemon.c - FUSE file system mapping daemon for GVFS
+ *
+ * Copyright (C) 2007-2008 Hans Petter Jansson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Hans Petter Jansson <hpj@novell.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/vfs.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <dbus/dbus.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <gio/gio.h>
+
+#include <glib/gurifuncs.h>
+
+/* stuff from common/ */
+#include <gdaemonmount.h>
+#include <gvfsdaemonprotocol.h>
+#include <gdbusutils.h>
+
+#define FUSE_USE_VERSION 26
+#include <fuse.h>
+
+#define DEBUG_ENABLED 0
+
+#define GET_FILE_HANDLE(fi) ((gpointer) (fi)->fh)
+#define SET_FILE_HANDLE(fi, fh) ((fi)->fh = (guint64) (fh))
+
+typedef struct {
+ time_t creation_time;
+ char *name;
+ GFile *root;
+} MountRecord;
+
+typedef enum {
+ FILE_OP_NONE,
+ FILE_OP_READ,
+ FILE_OP_WRITE
+} FileOp;
+
+typedef struct {
+ gint refcount;
+
+ GMutex *mutex;
+ gchar *path;
+ FileOp op;
+ gpointer stream;
+ goffset pos;
+} FileHandle;
+
+static GThread *subthread = NULL;
+static GMainLoop *subthread_main_loop = NULL;
+static GVfs *gvfs = NULL;
+
+static GVolumeMonitor *volume_monitor = NULL;
+
+/* Contains pointers to MountRecord */
+static GList *mount_list = NULL;
+static GMutex *mount_list_mutex;
+
+static time_t daemon_creation_time;
+static uid_t daemon_uid;
+static gid_t daemon_gid;
+
+static GStaticMutex global_mutex = G_STATIC_MUTEX_INIT;
+static GHashTable *global_path_to_fh_map = NULL;
+static GHashTable *global_active_fh_map = NULL;
+
+/* ------- *
+ * Helpers *
+ * ------- */
+
+static void
+debug_print (const gchar *message, ...)
+{
+#if DEBUG_ENABLED
+
+ static FILE *debug_fhd = NULL;
+ va_list var_args;
+ char *file;
+
+ if (!debug_fhd)
+ {
+ file = g_build_filename (g_get_home_dir (), "vfs.debug", NULL);
+ debug_fhd = fopen (file, "at");
+ g_free (file);
+ }
+
+ if (!debug_fhd)
+ return;
+
+ va_start (var_args, message);
+ g_vfprintf (debug_fhd, message, var_args);
+ va_end (var_args);
+
+ fflush (debug_fhd);
+
+#endif
+}
+
+typedef struct {
+ gint gioerror;
+ gint errno_value;
+} ErrorMap;
+
+static gint
+errno_from_error (GError *error)
+{
+ gint i;
+ static const ErrorMap error_map [] =
+ {
+ { G_IO_ERROR_FAILED, EIO },
+ { G_IO_ERROR_NOT_FOUND, ENOENT },
+ { G_IO_ERROR_EXISTS, EEXIST },
+ { G_IO_ERROR_IS_DIRECTORY, EISDIR },
+ { G_IO_ERROR_NOT_DIRECTORY, ENOTDIR },
+ { G_IO_ERROR_NOT_EMPTY, ENOTEMPTY },
+ { G_IO_ERROR_NOT_REGULAR_FILE, EIO },
+ { G_IO_ERROR_NOT_SYMBOLIC_LINK, EIO },
+ { G_IO_ERROR_NOT_MOUNTABLE_FILE, EIO },
+ { G_IO_ERROR_FILENAME_TOO_LONG, ENAMETOOLONG },
+ { G_IO_ERROR_INVALID_FILENAME, EIO },
+ { G_IO_ERROR_TOO_MANY_LINKS, ELOOP },
+ { G_IO_ERROR_NO_SPACE, ENOSPC },
+ { G_IO_ERROR_INVALID_ARGUMENT, EINVAL },
+ { G_IO_ERROR_PERMISSION_DENIED, EACCES },
+ { G_IO_ERROR_NOT_SUPPORTED, ENOTSUP },
+ { G_IO_ERROR_NOT_MOUNTED, EIO },
+ { G_IO_ERROR_ALREADY_MOUNTED, EIO },
+ { G_IO_ERROR_CLOSED, EIO },
+ { G_IO_ERROR_CANCELLED, EIO },
+ { G_IO_ERROR_PENDING, EIO },
+ { G_IO_ERROR_READ_ONLY, EACCES },
+ { G_IO_ERROR_CANT_CREATE_BACKUP, EIO },
+ { G_IO_ERROR_WRONG_ETAG, EIO },
+ { G_IO_ERROR_TIMED_OUT, EIO },
+ { G_IO_ERROR_BUSY, EBUSY },
+ { -1, -1 }
+ };
+
+ if (error->domain != G_IO_ERROR)
+ return EIO;
+
+ for (i = 0; error_map [i].gioerror >= 0; i++)
+ {
+ if (error_map [i].gioerror == error->code)
+ break;
+ }
+
+ if (error_map [i].gioerror >= 0)
+ return error_map [i].errno_value;
+
+ return EIO;
+}
+
+static FileHandle *
+file_handle_new (const gchar *path)
+{
+ FileHandle *file_handle;
+
+ file_handle = g_new0 (FileHandle, 1);
+ file_handle->refcount = 1;
+ file_handle->mutex = g_mutex_new ();
+ file_handle->op = FILE_OP_NONE;
+ file_handle->path = g_strdup (path);
+
+ g_hash_table_insert (global_active_fh_map, file_handle, file_handle);
+
+ return file_handle;
+}
+
+static FileHandle *
+file_handle_ref (FileHandle *file_handle)
+{
+ g_atomic_int_inc (&file_handle->refcount);
+ return file_handle;
+}
+
+static void
+file_handle_unref (FileHandle *file_handle)
+{
+ if (g_atomic_int_dec_and_test (&file_handle->refcount))
+ {
+ gint refs;
+
+ g_static_mutex_lock (&global_mutex);
+
+ /* Test again, since e.g. get_file_handle_for_path() might have
+ * snatched the global mutex and revived the file handle between
+ * g_atomic_int_dec_and_test() and us obtaining the global lock. */
+
+ refs = g_atomic_int_get (&file_handle->refcount);
+
+ if (refs == 0)
+ g_hash_table_remove (global_path_to_fh_map, file_handle->path);
+
+ g_static_mutex_unlock (&global_mutex);
+ }
+}
+
+static void
+file_handle_close_stream (FileHandle *file_handle)
+{
+ debug_print ("file_handle_close_stream\n");
+ if (file_handle->stream)
+ {
+ switch (file_handle->op)
+ {
+ case FILE_OP_READ:
+ g_input_stream_close (file_handle->stream, NULL, NULL);
+ break;
+
+ case FILE_OP_WRITE:
+ g_output_stream_close (file_handle->stream, NULL, NULL);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_object_unref (file_handle->stream);
+ file_handle->stream = NULL;
+ file_handle->op = FILE_OP_NONE;
+ }
+}
+
+/* Called on hash table removal */
+static void
+file_handle_free (FileHandle *file_handle)
+{
+ g_hash_table_remove (global_active_fh_map, file_handle);
+
+ file_handle_close_stream (file_handle);
+ g_mutex_free (file_handle->mutex);
+ g_free (file_handle->path);
+ g_free (file_handle);
+}
+
+static FileHandle *
+get_file_handle_for_path (const gchar *path)
+{
+ FileHandle *fh;
+
+ g_static_mutex_lock (&global_mutex);
+
+ fh = g_hash_table_lookup (global_path_to_fh_map, path);
+
+ if (fh)
+ file_handle_ref (fh);
+
+ g_static_mutex_unlock (&global_mutex);
+ return fh;
+}
+
+static FileHandle *
+get_or_create_file_handle_for_path (const gchar *path)
+{
+ FileHandle *fh;
+
+ g_static_mutex_lock (&global_mutex);
+
+ fh = g_hash_table_lookup (global_path_to_fh_map, path);
+
+ if (fh)
+ {
+ file_handle_ref (fh);
+ }
+ else
+ {
+ fh = file_handle_new (path);
+ g_hash_table_insert (global_path_to_fh_map, fh->path, fh);
+ }
+
+ g_static_mutex_unlock (&global_mutex);
+ return fh;
+}
+
+static FileHandle *
+get_file_handle_from_info (struct fuse_file_info *fi)
+{
+ FileHandle *fh;
+
+ g_static_mutex_lock (&global_mutex);
+
+ fh = GET_FILE_HANDLE (fi);
+
+ /* If the file handle is still valid, its value won't change. If
+ * invalid, it's set to NULL. */
+ fh = g_hash_table_lookup (global_active_fh_map, fh);
+
+ if (fh)
+ file_handle_ref (fh);
+
+ g_static_mutex_unlock (&global_mutex);
+ return fh;
+}
+
+static void
+reindex_file_handle_for_path (const gchar *old_path, const gchar *new_path)
+{
+ gchar *old_path_internal;
+ FileHandle *fh;
+
+ g_static_mutex_lock (&global_mutex);
+
+ if (!g_hash_table_lookup_extended (global_path_to_fh_map, old_path,
+ (gpointer *) &old_path_internal,
+ (gpointer *) &fh))
+ goto out;
+
+ g_hash_table_steal (global_path_to_fh_map, old_path);
+
+ g_free (fh->path);
+ fh->path = g_strdup (new_path);
+
+ g_hash_table_insert (global_path_to_fh_map, fh->path, fh);
+
+ out:
+ g_static_mutex_unlock (&global_mutex);
+}
+
+static MountRecord *
+mount_record_new (GMount *mount)
+{
+ MountRecord *mount_record;
+ char *name;
+
+ mount_record = g_new (MountRecord, 1);
+
+ mount_record->root = g_mount_get_root (mount);
+ name = g_object_get_data (G_OBJECT (mount), "g-stable-name");
+ if (name != NULL && *name != 0)
+ name = g_strdup (name);
+ else
+ name = g_mount_get_name (mount);
+
+ /* Keep in sync with gvfs daemon mount tracker */
+ mount_record->name = g_uri_escape_string (name, "+@#$., ", TRUE);
+ g_free (name);
+ mount_record->creation_time = time (NULL);
+
+ return mount_record;
+}
+
+static void
+mount_record_free (MountRecord *mount_record)
+{
+ g_object_unref (mount_record->root);
+ g_free (mount_record->name);
+ g_free (mount_record);
+}
+
+static void
+mount_list_lock (void)
+{
+ g_mutex_lock (mount_list_mutex);
+}
+
+static void
+mount_list_unlock (void)
+{
+ g_mutex_unlock (mount_list_mutex);
+}
+
+static void
+mount_list_free (void)
+{
+ g_list_foreach (mount_list, (GFunc) mount_record_free, NULL);
+ g_list_free (mount_list);
+ mount_list = NULL;
+}
+
+static gboolean
+mount_record_for_mount_exists (GMount *mount)
+{
+ GList *l;
+ GFile *root;
+ gboolean res;
+
+ g_assert (mount != NULL);
+
+ root = g_mount_get_root (mount);
+
+ res = FALSE;
+
+ mount_list_lock ();
+
+ for (l = mount_list; l != NULL; l = l->next)
+ {
+ MountRecord *this_mount_record = l->data;
+
+ if (g_file_equal (root, this_mount_record->root))
+ {
+ res = TRUE;
+ break;
+ }
+ }
+
+ mount_list_unlock ();
+
+ g_object_unref (root);
+
+ return res;
+}
+
+static GFile *
+mount_record_find_root_by_mount_name (const gchar *mount_name)
+{
+ GList *l;
+ GFile *root;
+
+ g_assert (mount_name != NULL);
+
+ root = NULL;
+
+ mount_list_lock ();
+
+ for (l = mount_list; l != NULL; l = l->next)
+ {
+ MountRecord *mount_record = l->data;
+
+ if (strcmp (mount_name, mount_record->name) == 0)
+ {
+ root = g_object_ref (mount_record->root);
+ break;
+ }
+ }
+
+ mount_list_unlock ();
+
+ return root;
+}
+
+static void
+mount_list_update (void)
+{
+ GList *mounts;
+ GList *l;
+
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = l->data;
+
+ if (!mount_record_for_mount_exists (mount))
+ {
+ mount_list_lock ();
+ mount_list = g_list_prepend (mount_list, mount_record_new (mount));
+ mount_list_unlock ();
+ }
+
+ g_object_unref (mount);
+ }
+
+ g_list_free (mounts);
+}
+
+#if 0
+
+static gint
+file_info_get_attribute_as_int (GFileInfo *file_info, const gchar *attribute)
+{
+ GFileAttributeType attribute_type;
+ gint int_result;
+
+ attribute_type = g_file_info_get_attribute_type (file_info, attribute);
+
+ switch (attribute_type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ int_result = g_file_info_get_attribute_uint32 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ int_result = g_file_info_get_attribute_int32 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ int_result = g_file_info_get_attribute_uint64 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ int_result = g_file_info_get_attribute_int64 (file_info, attribute);
+ break;
+
+ default:
+ int_result = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ return int_result;
+}
+
+#endif
+
+static guint
+file_info_get_attribute_as_uint (GFileInfo *file_info, const gchar *attribute)
+{
+ GFileAttributeType attribute_type;
+ guint uint_result;
+
+ attribute_type = g_file_info_get_attribute_type (file_info, attribute);
+
+ switch (attribute_type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ uint_result = g_file_info_get_attribute_uint32 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ uint_result = g_file_info_get_attribute_int32 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ uint_result = g_file_info_get_attribute_uint64 (file_info, attribute);
+ break;
+
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ uint_result = g_file_info_get_attribute_int64 (file_info, attribute);
+ break;
+
+ default:
+ uint_result = 0;
+ g_assert_not_reached ();
+ break;
+ }
+
+ return uint_result;
+}
+
+static gboolean
+path_is_mount_list (const gchar *path)
+{
+ while (*path == '/')
+ path++;
+
+ return *path == 0;
+}
+
+
+static GFile *
+file_from_full_path (const gchar *path)
+{
+ gchar *mount_name;
+ GFile *file = NULL;
+ const gchar *s1, *s2;
+ GFile *root;
+
+ file = NULL;
+
+ s1 = path;
+ while (*s1 == '/')
+ s1++;
+
+ if (*s1)
+ {
+ s2 = strchr (s1, '/');
+ if (s2 == NULL)
+ s2 = s1 + strlen (s1);
+
+ mount_name = g_strndup (s1, s2 - s1);
+ root = mount_record_find_root_by_mount_name (mount_name);
+ g_free (mount_name);
+
+ if (root)
+ {
+ while (*s2 == '/')
+ s2++;
+ file = g_file_resolve_relative_path (root, s2);
+ g_object_unref (root);
+ }
+ }
+
+ return file;
+}
+
+/* ------------- *
+ * VFS functions *
+ * ------------- */
+
+#if 0
+
+/* A stat -f <path> on a FUSE mount always results in this function being called with a path
+ * of '/'. This means we can't return valid info for the various mounts. Hopefully we can
+ * fix this in the future. */
+
+static gint
+vfs_statfs (const gchar *path, struct statvfs *stbuf)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_statfs: %s\n", path);
+
+ if ((file = file_from_full_path (path)))
+ {
+ GFileInfo *file_info;
+
+ file_info = g_file_get_filesystem_info (file, "*", NULL, &error);
+
+ if (file_info)
+ {
+ memset (stbuf, 0, sizeof (*stbuf));
+
+ stbuf->f_bsize = 4096;
+ stbuf->f_frsize = 4096; /* Ignored by FUSE */
+ stbuf->f_blocks = 0;
+ stbuf->f_bfree = 0;
+ stbuf->f_bavail = 0;
+ stbuf->f_files = 0;
+ stbuf->f_ffree = 0;
+ stbuf->f_favail = 0; /* Ignored by FUSE */
+ stbuf->f_fsid = 1; /* Ignored by FUSE */
+ stbuf->f_flag = 0; /* Ignored by FUSE */
+ stbuf->f_namemax = 1024;
+
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE))
+ stbuf->f_blocks = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE) / 4096;
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
+ stbuf->f_bfree = stbuf->f_bavail = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE) / 4096;
+ }
+ else if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ g_object_unref (file);
+ }
+
+ debug_print ("vfs_statfs: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+#endif
+
+static gint
+vfs_statfs (const gchar *path, struct statvfs *stbuf)
+{
+ gint result = 0;
+
+ debug_print ("vfs_statfs: %s\n", path);
+
+ memset (stbuf, 0, sizeof (*stbuf));
+
+ stbuf->f_bsize = 4096;
+ stbuf->f_frsize = 4096; /* Ignored by FUSE */
+ stbuf->f_blocks = 0;
+ stbuf->f_bfree = 0;
+ stbuf->f_bavail = 0;
+ stbuf->f_files = 0;
+ stbuf->f_ffree = 0;
+ stbuf->f_favail = 0; /* Ignored by FUSE */
+ stbuf->f_fsid = 1; /* Ignored by FUSE */
+ stbuf->f_flag = 0; /* Ignored by FUSE */
+ stbuf->f_namemax = 1024;
+
+ debug_print ("vfs_statfs: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static mode_t
+file_info_get_stat_mode (GFileInfo *file_info)
+{
+ GFileType file_type;
+ mode_t unix_mode;
+
+ file_type = g_file_info_get_file_type (file_info);
+
+ switch (file_type)
+ {
+ case G_FILE_TYPE_REGULAR:
+ unix_mode = S_IFREG;
+ break;
+
+ case G_FILE_TYPE_DIRECTORY:
+ case G_FILE_TYPE_MOUNTABLE:
+ unix_mode = S_IFDIR;
+ break;
+
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ case G_FILE_TYPE_SHORTCUT:
+ unix_mode = S_IFLNK;
+ break;
+
+ case G_FILE_TYPE_SPECIAL:
+ default:
+ unix_mode = 0;
+ break;
+ }
+
+ if (file_type == G_FILE_TYPE_DIRECTORY ||
+ !g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) ||
+ g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
+ unix_mode |= S_IRUSR;
+ if (!g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) ||
+ g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
+ unix_mode |= S_IWUSR;
+ if (file_type == G_FILE_TYPE_DIRECTORY ||
+ !g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) ||
+ g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
+ unix_mode |= S_IXUSR;
+
+ return unix_mode;
+}
+
+static gint
+getattr_for_file (GFile *file, struct stat *sbuf)
+{
+ GFileInfo *file_info;
+ GError *error = NULL;
+ gint result = 0;
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_UNIX_MODE ","
+ G_FILE_ATTRIBUTE_TIME_CHANGED ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED ","
+ G_FILE_ATTRIBUTE_TIME_ACCESS ","
+ G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE ","
+ G_FILE_ATTRIBUTE_UNIX_BLOCKS,
+ 0, NULL, &error);
+
+ if (file_info)
+ {
+ GTimeVal mod_time;
+
+ sbuf->st_mode = file_info_get_stat_mode (file_info);
+ sbuf->st_size = g_file_info_get_size (file_info);
+ sbuf->st_uid = daemon_uid;
+ sbuf->st_gid = daemon_gid;
+
+ g_file_info_get_modification_time (file_info, &mod_time);
+ sbuf->st_mtime = mod_time.tv_sec;
+ sbuf->st_ctime = mod_time.tv_sec;
+ sbuf->st_atime = mod_time.tv_sec;
+
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_TIME_CHANGED))
+ sbuf->st_ctime = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_TIME_CHANGED);
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS))
+ sbuf->st_atime = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS);
+
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE))
+ sbuf->st_blksize = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE);
+ if (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_UNIX_BLOCKS))
+ sbuf->st_blocks = file_info_get_attribute_as_uint (file_info, G_FILE_ATTRIBUTE_UNIX_BLOCKS);
+ else /* fake it to make 'du' work like 'du --apparent'. */
+ sbuf->st_blocks = (sbuf->st_size + 511) / 512;
+
+ /* Setting st_nlink to 1 for directories makes 'find' work */
+ sbuf->st_nlink = 1;
+
+ g_object_unref (file_info);
+ }
+ else
+ {
+ if (error)
+ {
+ debug_print ("Error from GVFS: %s\n", error->message);
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ debug_print ("No file info, but no error from GVFS.\n");
+ result = -EIO;
+ }
+ }
+
+ return result;
+}
+
+static gint
+vfs_getattr (const gchar *path, struct stat *sbuf)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_getattr: %s\n", path);
+
+ memset (sbuf, 0, sizeof (*sbuf));
+
+ sbuf->st_dev = 0; /* dev_t ID of device containing file */
+ sbuf->st_ino = 0; /* ino_t inode number */
+ sbuf->st_uid = 0; /* uid_t user ID of owner */
+ sbuf->st_gid = 0; /* gid_t group ID of owner */
+ sbuf->st_rdev = 0; /* dev_t device ID (if special file) */
+ sbuf->st_size = 0; /* off_t total size, in bytes */
+ sbuf->st_blocks = 0; /* blkcnt_t number of blocks allocated */
+ sbuf->st_atime = 0; /* time_t time of last access */
+ sbuf->st_mtime = 0; /* time_t time of last modification */
+ sbuf->st_ctime = 0; /* time_t time of last status change */
+ sbuf->st_blksize = 4096; /* blksize_t blocksize for filesystem I/O */
+
+ if (path_is_mount_list (path))
+ {
+ /* Mount list */
+
+ sbuf->st_mode = S_IFDIR | 0500; /* mode_t protection */
+ sbuf->st_nlink = 2 + g_list_length (mount_list); /* nlink_t number of hard links */
+ sbuf->st_atime = daemon_creation_time;
+ sbuf->st_mtime = daemon_creation_time;
+ sbuf->st_ctime = daemon_creation_time;
+ sbuf->st_uid = daemon_uid;
+ sbuf->st_gid = daemon_gid;
+ }
+ else if ((file = file_from_full_path (path)))
+ {
+ /* Submount */
+
+ result = getattr_for_file (file, sbuf);
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_getattr: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_readlink (const gchar *path, gchar *target, size_t size)
+{
+ debug_print ("vfs_readlink: %s\n", path);
+
+ return 0;
+}
+
+static gint
+setup_input_stream (GFile *file, FileHandle *fh)
+{
+ GError *error = NULL;
+ gint result = 0;
+
+ if (fh->stream)
+ {
+ debug_print ("setup_input_stream: have stream\n");
+
+ if (fh->op == FILE_OP_READ)
+ {
+ debug_print ("setup_input_stream: doing read\n");
+ }
+ else
+ {
+ debug_print ("setup_input_stream: doing write\n");
+
+ g_output_stream_close (fh->stream, NULL, NULL);
+ g_object_unref (fh->stream);
+ fh->stream = NULL;
+ }
+ }
+
+ if (!fh->stream)
+ {
+ debug_print ("setup_input_stream: no stream\n");
+ fh->stream = g_file_read (file, NULL, &error);
+ fh->pos = 0;
+ }
+
+ if (fh->stream)
+ fh->op = FILE_OP_READ;
+ else
+ fh->op = FILE_OP_NONE;
+
+ if (error)
+ {
+ debug_print ("setup_input_stream: error\n");
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ return result;
+}
+
+static gint
+setup_output_stream (GFile *file, FileHandle *fh)
+{
+ GError *error = NULL;
+ gint result = 0;
+
+ if (fh->stream)
+ {
+ if (fh->op == FILE_OP_WRITE)
+ {
+ }
+ else
+ {
+ g_input_stream_close (fh->stream, NULL, NULL);
+ g_object_unref (fh->stream);
+ fh->stream = NULL;
+ }
+ }
+
+ if (!fh->stream)
+ {
+ fh->stream = g_file_append_to (file, 0, NULL, &error);
+ if (fh->stream)
+ fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream));
+ }
+
+ if (fh->stream)
+ fh->op = FILE_OP_WRITE;
+ else
+ fh->op = FILE_OP_NONE;
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ return result;
+}
+
+static gint
+vfs_open (const gchar *path, struct fuse_file_info *fi)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_open: %s\n", path);
+
+ if (path_is_mount_list (path))
+ result = -EISDIR;
+ else if ((file = file_from_full_path (path)))
+ {
+ GFileInfo *file_info;
+ GError *error = NULL;
+
+ file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
+
+ if (file_info)
+ {
+ GFileType file_type = g_file_info_get_file_type (file_info);
+
+ if (file_type == G_FILE_TYPE_REGULAR)
+ {
+ FileHandle *fh = get_or_create_file_handle_for_path (path);
+
+ g_mutex_lock (fh->mutex);
+
+ /* File exists */
+
+ SET_FILE_HANDLE (fi, fh);
+
+ debug_print ("vfs_open: flags=%o\n", fi->flags);
+
+ /* Set up a stream here, so we can check for errors */
+
+ if (fi->flags & O_WRONLY || fi->flags & O_RDWR)
+ result = setup_output_stream (file, fh);
+ else
+ result = setup_input_stream (file, fh);
+
+ g_mutex_unlock (fh->mutex);
+
+ /* The added reference to the file handle is released in vfs_release() */
+ }
+ else if (file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ /* EISDIR is supposedly only for attempts to write to directory handles,
+ * but outside readdir(), we don't support reading them either. */
+ result = -EISDIR;
+ }
+ else
+ {
+ result = -EACCES;
+ }
+
+ g_object_unref (file_info);
+ }
+ else
+ {
+ if (error)
+ {
+ debug_print ("Error from GVFS: %s\n", error->message);
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ debug_print ("No file info, but no error from GVFS.\n");
+ result = -EIO;
+ }
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_open: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_create (const gchar *path, mode_t mode, struct fuse_file_info *fi)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_create: %s\n", path);
+
+ if (path_is_mount_list (path))
+ result = -EEXIST;
+ if ((file = file_from_full_path (path)))
+ {
+ GFileInfo *file_info;
+ GError *error = NULL;
+
+ file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
+
+ if (file_info)
+ {
+ result = -EEXIST;
+ g_object_unref (file_info);
+ }
+ else
+ {
+ GFileOutputStream *file_output_stream;
+
+ if (error)
+ {
+ g_error_free (error);
+ error = NULL;
+ }
+
+ file_output_stream = g_file_create (file, 0, NULL, &error);
+ if (file_output_stream)
+ {
+ FileHandle *fh = get_or_create_file_handle_for_path (path);
+
+ /* Success */
+
+ g_mutex_lock (fh->mutex);
+
+ SET_FILE_HANDLE (fi, fh);
+
+ file_handle_close_stream (fh);
+ fh->stream = file_output_stream;
+ fh->op = FILE_OP_WRITE;
+
+ g_mutex_unlock (fh->mutex);
+
+ /* The added reference to the file handle is released in vfs_release() */
+ }
+ else
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_create: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_release (const gchar *path, struct fuse_file_info *fi)
+{
+ FileHandle *fh = get_file_handle_from_info (fi);
+
+ debug_print ("vfs_release: %s\n", path);
+
+ if (fh)
+ {
+ /* get_file_handle_from_info () adds a "working ref", so unref twice. */
+ file_handle_unref (fh);
+ file_handle_unref (fh);
+ }
+
+ return 0;
+}
+
+static gint
+read_stream (FileHandle *fh, gchar *output_buf, size_t output_buf_size, off_t offset)
+{
+ GInputStream *input_stream;
+ gint n_bytes_skipped = 0;
+ gint n_bytes_read = 0;
+ gint result = 0;
+ GError *error = NULL;
+
+ input_stream = fh->stream;
+
+ if (offset != fh->pos)
+ {
+ if (g_seekable_can_seek (G_SEEKABLE (input_stream)))
+ {
+ /* Can seek */
+
+ debug_print ("read_stream: seeking to offset %d.\n", offset);
+
+ if (g_seekable_seek (G_SEEKABLE (input_stream), offset, G_SEEK_SET, NULL, &error))
+ {
+ fh->pos = offset;
+ }
+ else
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ else if (offset > fh->pos)
+ {
+ /* Can skip ahead */
+
+ debug_print ("read_stream: skipping to offset %d.\n", offset);
+
+ n_bytes_skipped = g_input_stream_skip (input_stream, offset - fh->pos, NULL, &error);
+
+ if (n_bytes_skipped > 0)
+ fh->pos += n_bytes_skipped;
+
+ if (n_bytes_skipped != offset - fh->pos)
+ {
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ result = -EIO;
+ }
+ }
+ }
+ else
+ {
+ /* Can't seek, can't skip backwards */
+
+ debug_print ("read_stream: can't seek nor skip to offset %d!\n", offset);
+
+ result = -ENOTSUP;
+ }
+ }
+
+ if (result == 0)
+ {
+ while (n_bytes_read < output_buf_size)
+ {
+ gboolean part_result;
+ gsize part_bytes_read = 0;
+
+ part_result = g_input_stream_read_all (input_stream,
+ output_buf + n_bytes_read,
+ output_buf_size - n_bytes_read,
+ &part_bytes_read,
+ NULL,
+ &error);
+
+ n_bytes_read += part_bytes_read;
+ fh->pos += part_bytes_read;
+
+ if (!part_result || part_bytes_read == 0)
+ break;
+ }
+
+ result = n_bytes_read;
+
+ if (n_bytes_read < output_buf_size)
+ {
+ debug_print ("read_stream: wanted %d bytes, but got %d.\n", output_buf_size, n_bytes_read);
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ }
+
+ return result;
+}
+
+static gint
+vfs_read (const gchar *path, gchar *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_read: %s\n", path);
+
+ if ((file = file_from_full_path (path)))
+ {
+ FileHandle *fh = get_file_handle_from_info (fi);
+
+ if (fh)
+ {
+ g_mutex_lock (fh->mutex);
+
+ result = setup_input_stream (file, fh);
+
+ if (result == 0)
+ {
+ result = read_stream (fh, buf, size, offset);
+ }
+ else
+ {
+ debug_print ("vfs_read: failed to setup input_stream!\n");
+ }
+
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+ else
+ {
+ result = -EINVAL;
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ if (result < 0)
+ debug_print ("vfs_read: -> %s\n", g_strerror (-result));
+ else
+ debug_print ("vfs_read: -> %d bytes read.\n", result);
+
+ return result;
+}
+
+static gint
+write_stream (FileHandle *fh, const gchar *input_buf, size_t input_buf_size, off_t offset)
+{
+ GOutputStream *output_stream;
+ gint n_bytes_written = 0;
+ gint result = 0;
+ GError *error = NULL;
+
+ debug_print ("write_stream: %d bytes at offset %d.\n", input_buf_size, offset);
+
+ output_stream = fh->stream;
+
+ if (offset != fh->pos)
+ {
+ if (g_seekable_can_seek (G_SEEKABLE (output_stream)))
+ {
+ /* Can seek */
+
+ if (g_seekable_seek (G_SEEKABLE (output_stream), offset, G_SEEK_SET, NULL, &error))
+ {
+ fh->pos = offset;
+ }
+ else
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ /* Can't seek, and output streams can't skip */
+
+ result = -ENOTSUP;
+ }
+ }
+
+ if (result == 0)
+ {
+ while (n_bytes_written < input_buf_size)
+ {
+ gboolean part_result;
+ gsize part_bytes_written = 0;
+
+ part_result = g_output_stream_write_all (output_stream,
+ (void *) (input_buf + n_bytes_written),
+ input_buf_size - n_bytes_written,
+ &part_bytes_written,
+ NULL,
+ &error);
+
+ n_bytes_written += part_bytes_written;
+ fh->pos += part_bytes_written;
+
+ if (!part_result)
+ break;
+ }
+
+ result = n_bytes_written;
+
+ if (n_bytes_written < input_buf_size)
+ {
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ else if (!g_output_stream_flush (output_stream, NULL, &error))
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+
+ return result;
+}
+
+static gint
+vfs_write (const gchar *path, const gchar *buf, size_t len, off_t offset,
+ struct fuse_file_info *fi)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_write: %s\n", path);
+
+ if ((file = file_from_full_path (path)))
+ {
+ FileHandle *fh = get_file_handle_from_info (fi);
+
+ if (fh)
+ {
+ g_mutex_lock (fh->mutex);
+
+ result = setup_output_stream (file, fh);
+ if (result == 0)
+ {
+ result = write_stream (fh, buf, len, offset);
+ }
+
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+ else
+ {
+ result = -EINVAL;
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ if (result < 0)
+ debug_print ("vfs_write: -> %s\n", g_strerror (-result));
+ else
+ debug_print ("vfs_write: -> %d bytes written.\n", result);
+
+ return result;
+}
+
+static gint
+vfs_flush (const gchar *path, struct fuse_file_info *fi)
+{
+ debug_print ("vfs_flush: %s\n", path);
+
+ return 0;
+}
+
+static gint
+vfs_opendir (const gchar *path, struct fuse_file_info *fi)
+{
+ GFile *file;
+ gint result = 0;
+
+ debug_print ("vfs_opendir: %s\n", path);
+
+ if (path_is_mount_list (path))
+ {
+ /* Mount list */
+ }
+ else if ((file = file_from_full_path (path)) != NULL)
+ {
+ /* Submount */
+
+ /* TODO: Check that path exists */
+
+ g_object_unref (file);
+ }
+ else
+ {
+ /* Not found */
+
+ result = -ENOENT;
+ }
+
+ return result;
+}
+
+static gint
+readdir_for_file (GFile *base_file, gpointer buf, fuse_fill_dir_t filler)
+{
+ GFileEnumerator *enumerator;
+ GFileInfo *file_info;
+ GError *error = NULL;
+
+ g_assert (base_file != NULL);
+
+ enumerator = g_file_enumerate_children (base_file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
+ if (!enumerator)
+ {
+ gint result;
+
+ if (error)
+ {
+ debug_print ("Error from GVFS: %s\n", error->message);
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ debug_print ("No file info, but no error from GVFS.\n");
+ result = -EIO;
+ }
+
+ return result;
+ }
+
+ filler (buf, ".", NULL, 0);
+ filler (buf, "..", NULL, 0);
+
+ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
+ {
+ filler (buf, g_file_info_get_name (file_info), NULL, 0);
+ g_object_unref (file_info);
+ }
+
+ g_object_unref (enumerator);
+
+ return 0;
+}
+
+static gint
+vfs_readdir (const gchar *path, gpointer buf, fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi)
+{
+ GFile *base_file;
+ gint result = 0;
+
+ debug_print ("vfs_readdir: %s\n", path);
+
+ if (path_is_mount_list (path))
+ {
+ GList *l;
+
+ /* Mount list */
+
+ filler (buf, ".", NULL, 0);
+ filler (buf, "..", NULL, 0);
+
+ mount_list_lock ();
+
+ for (l = mount_list; l; l = g_list_next (l))
+ {
+ MountRecord *mount_record = l->data;
+
+ filler (buf, mount_record->name, NULL, 0);
+ }
+
+ mount_list_unlock ();
+ }
+ else if ((base_file = file_from_full_path (path)))
+ {
+ /* Submount */
+
+ result = readdir_for_file (base_file, buf, filler);
+
+ g_object_unref (base_file);
+ }
+ else
+ {
+ /* Not found */
+
+ result = -ENOENT;
+ }
+
+ return result;
+}
+
+static gint
+vfs_rename (const gchar *old_path, const gchar *new_path)
+{
+ GFile *old_file;
+ GFile *new_file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_rename: %s -> %s\n", old_path, new_path);
+
+ old_file = file_from_full_path (old_path);
+ new_file = file_from_full_path (new_path);
+
+ if (old_file && new_file)
+ {
+ FileHandle *fh = get_file_handle_for_path (old_path);
+
+ if (fh)
+ {
+ g_mutex_lock (fh->mutex);
+ file_handle_close_stream (fh);
+ }
+
+ g_file_move (old_file, new_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
+
+ if (error)
+ {
+ debug_print ("vfs_rename failed: %s\n", error->message);
+
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ reindex_file_handle_for_path (old_path, new_path);
+ }
+
+ if (fh)
+ {
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+
+ if (result == -EISDIR)
+ {
+ /* This makes e.g. 'mv' fall back to a recursive copy + delete operation */
+ result = -EXDEV;
+ }
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ if (old_file)
+ g_object_unref (old_file);
+ if (new_file)
+ g_object_unref (new_file);
+
+ debug_print ("vfs_rename: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_unlink (const gchar *path)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_unlink: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ FileHandle *fh = get_file_handle_for_path (path);
+
+ if (fh)
+ {
+ g_mutex_lock (fh->mutex);
+ file_handle_close_stream (fh);
+ }
+
+ g_file_delete (file, NULL, &error);
+
+ if (fh)
+ {
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+
+ if (error)
+ {
+ debug_print ("vfs_unlink failed: %s (%s)\n", path, error->message);
+
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_unlink: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_mkdir (const gchar *path, mode_t mode)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_mkdir: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ if (g_file_make_directory (file, NULL, &error))
+ {
+ /* Ignore errors setting the mode. We already created the directory, and that's
+ * good enough. */
+ g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, mode, 0, NULL, NULL);
+ }
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_mkdir: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_rmdir (const gchar *path)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_rmdir: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ GFileInfo *file_info;
+
+ file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
+ if (file_info)
+ {
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+ {
+ g_file_delete (file, NULL, &error);
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ result = -ENOTDIR;
+ }
+ }
+ else
+ {
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+ }
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_rmdir: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gboolean
+file_handle_get_size (FileHandle *fh,
+ goffset *size)
+{
+ GFileInfo *info;
+ gboolean res;
+
+ if (fh->stream == NULL)
+ return FALSE;
+
+ info = NULL;
+ if (fh->op == FILE_OP_READ)
+ info = g_file_input_stream_query_info (fh->stream,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ NULL, NULL);
+ else if (fh->op == FILE_OP_WRITE)
+ info = g_file_output_stream_query_info (fh->stream,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ NULL, NULL);
+
+ res = FALSE;
+ if (info)
+ {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
+ {
+ *size = g_file_info_get_size (info);
+ res = TRUE;
+ }
+ g_object_unref (info);
+ }
+ return res;
+}
+
+static gint
+vfs_ftruncate (const gchar *path, off_t size, struct fuse_file_info *fi)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+ goffset current_size;
+
+ debug_print ("vfs_ftruncate: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ FileHandle *fh = get_file_handle_from_info (fi);
+
+ if (fh)
+ {
+ g_mutex_lock (fh->mutex);
+
+ result = setup_output_stream (file, fh);
+
+ if (result == 0)
+ {
+ if (g_seekable_can_truncate (G_SEEKABLE (fh->stream)))
+ {
+ g_seekable_truncate (fh->stream, size, NULL, &error);
+ }
+ else if (size == 0)
+ {
+ g_output_stream_close (fh->stream, NULL, NULL);
+ g_object_unref (fh->stream);
+ fh->stream = NULL;
+
+ fh->stream = g_file_replace (file, 0, FALSE, 0, NULL, &error);
+
+ if (fh->stream != NULL)
+ {
+ /* The stream created by g_file_replace() won't always replace
+ * the file until it's been closed. So close it now to make
+ * future operations consistent. */
+ g_output_stream_close (fh->stream, NULL, NULL);
+ g_object_unref (fh->stream);
+ fh->stream = NULL;
+ }
+ }
+ else if (file_handle_get_size (fh, &current_size) &&
+ current_size == size)
+ {
+ /* Don't have to do anything to succeed */
+ }
+ else
+ {
+ result = -ENOTSUP;
+ }
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+ else
+ {
+ result = -EINVAL;
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_ftruncate: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_truncate (const gchar *path, off_t size)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_truncate: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ GFileOutputStream *file_output_stream = NULL;
+ FileHandle *fh;
+
+ /* Get a file handle just to lock the path while we're working */
+ fh = get_file_handle_for_path (path);
+ if (fh)
+ g_mutex_lock (fh->mutex);
+
+ if (size == 0)
+ {
+ file_output_stream = g_file_replace (file, 0, FALSE, 0, NULL, &error);
+ }
+ else
+ {
+ file_output_stream = g_file_append_to (file, 0, NULL, &error);
+ if (file_output_stream)
+ g_seekable_truncate (G_SEEKABLE (file_output_stream), size, NULL, &error);
+ }
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ if (file_output_stream)
+ {
+ g_output_stream_close (G_OUTPUT_STREAM (file_output_stream), NULL, NULL);
+ g_object_unref (file_output_stream);
+ }
+
+ if (fh)
+ {
+ g_mutex_unlock (fh->mutex);
+ file_handle_unref (fh);
+ }
+
+ g_object_unref (file);
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_truncate: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_symlink (const gchar *path_old, const gchar *path_new)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_symlink: %s -> %s\n", path_new, path_old);
+
+ file = file_from_full_path (path_new);
+
+ if (file)
+ {
+ g_file_make_symbolic_link (file, path_old, NULL, &error);
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_symlink: -> %s\n", g_strerror (-result));
+
+ return result;
+}
+
+static gint
+vfs_access (const gchar *path, gint mode)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_access: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ GFileInfo *file_info;
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_READ ","
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE ","
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE ",",
+ 0, NULL, &error);
+ if (file_info)
+ {
+ if ((mode & R_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) &&
+ !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ))) ||
+ (mode & W_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) &&
+ !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))) ||
+ (mode & X_OK && (g_file_info_has_attribute (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) &&
+ !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))))
+ result = -EACCES;
+
+ g_object_unref (file_info);
+ }
+ else if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ g_object_unref (file);
+ }
+ else if (path_is_mount_list (path))
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_access: -> %s\n", g_strerror (-result));
+ return result;
+}
+
+static gint
+vfs_utimens (const gchar *path, const struct timespec tv [2])
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ debug_print ("vfs_utimens: %s\n", path);
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ guint64 atime;
+ guint64 mtime;
+
+ if (tv)
+ {
+ atime = (guint64) tv [0].tv_sec * 1000000 + (guint64) tv [0].tv_nsec / (guint64) 1000;
+ mtime = (guint64) tv [1].tv_sec * 1000000 + (guint64) tv [1].tv_nsec / (guint64) 1000;
+ }
+ else
+ {
+ struct timeval tiv;
+
+ gettimeofday (&tiv, NULL);
+ atime = (guint64) tiv.tv_sec * (guint64) 1000000 + (guint64) tiv.tv_usec;
+ mtime = atime;
+ }
+
+ g_file_set_attribute (file, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
+ G_FILE_ATTRIBUTE_TYPE_UINT64, &atime,
+ 0, NULL, &error);
+
+ if (!error)
+ {
+ g_file_set_attribute (file, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
+ G_FILE_ATTRIBUTE_TYPE_UINT64, &mtime,
+ 0, NULL, &error);
+ }
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+ }
+ else if (path_is_mount_list (path))
+ {
+ /* */
+ }
+ else
+ {
+ result = -ENOENT;
+ }
+
+ debug_print ("vfs_utimens: -> %s\n", g_strerror (-result));
+ return result;
+}
+
+static gint
+vfs_chmod (const gchar *path, mode_t mode)
+{
+ GFile *file;
+ GError *error = NULL;
+ gint result = 0;
+
+ file = file_from_full_path (path);
+
+ if (file)
+ {
+ g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, mode, 0, NULL, &error);
+
+ if (error)
+ {
+ result = -errno_from_error (error);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+ }
+
+ return result;
+}
+
+static void
+mount_tracker_mounted_cb (GVolumeMonitor *volume_monitor,
+ GMount *mount)
+{
+ MountRecord *mount_record;
+
+ if (mount_record_for_mount_exists (mount))
+ return;
+
+ mount_record = mount_record_new (mount);
+
+ mount_list_lock ();
+ mount_list = g_list_prepend (mount_list, mount_record);
+ mount_list_unlock ();
+}
+
+static void
+mount_tracker_unmounted_cb (GVolumeMonitor *volume_monitor,
+ GMount *mount)
+{
+ GFile *root;
+ GList *l;
+
+ root = g_mount_get_root (mount);
+
+ mount_list_lock ();
+
+ root = g_mount_get_root (mount);
+
+ for (l = mount_list; l != NULL; l = l->next)
+ {
+ MountRecord *mount_record = l->data;
+
+ if (g_file_equal (root, mount_record->root))
+ {
+ mount_list = g_list_delete_link (mount_list, l);
+ mount_record_free (mount_record);
+ break;
+ }
+ }
+
+ mount_list_unlock ();
+
+ g_object_unref (root);
+}
+
+static gpointer
+subthread_main (gpointer data)
+{
+
+ mount_list_update ();
+
+ g_signal_connect (volume_monitor, "mount_added", (GCallback) mount_tracker_mounted_cb, NULL);
+ g_signal_connect (volume_monitor, "mount_removed", (GCallback) mount_tracker_unmounted_cb, NULL);
+
+ g_main_loop_run (subthread_main_loop);
+
+ g_signal_handlers_disconnect_by_func (volume_monitor, mount_tracker_mounted_cb, NULL);
+ g_signal_handlers_disconnect_by_func (volume_monitor, mount_tracker_unmounted_cb, NULL);
+
+ g_main_loop_unref (subthread_main_loop);
+ subthread_main_loop = NULL;
+
+ g_object_unref (volume_monitor);
+ volume_monitor = NULL;
+
+ /* Tell the main thread to unmount. Using kill() is necessary according to FUSE maintainers. */
+ kill (getpid (), SIGHUP);
+
+ return NULL;
+}
+
+static DBusHandlerResult
+dbus_filter_func (DBusConnection *connection,
+ DBusMessage *message,
+ void *data)
+{
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ const char *service, *old_owner, *new_owner;
+
+ dbus_message_get_args (message,
+ NULL,
+ DBUS_TYPE_STRING, &service,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID);
+
+ /* Handle monitor owner going away */
+ if (service != NULL &&
+ strcmp (G_VFS_DBUS_DAEMON_NAME, service) == 0 &&
+ *new_owner == 0)
+ {
+ /* The daemon died, unmount */
+ g_main_loop_quit (subthread_main_loop);
+ }
+ }
+ else if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected"))
+ {
+ /* Session bus died, unmount */
+ g_main_loop_quit (subthread_main_loop);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gpointer
+vfs_init (struct fuse_conn_info *conn)
+{
+ DBusConnection *dbus_conn;
+ DBusMessage *message;
+ DBusError error;
+
+ daemon_creation_time = time (NULL);
+ daemon_uid = getuid ();
+ daemon_gid = getgid ();
+
+ mount_list_mutex = g_mutex_new ();
+ global_path_to_fh_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) file_handle_free);
+ global_active_fh_map = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, NULL);
+
+ dbus_error_init (&error);
+
+ dbus_conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ if (dbus_conn == NULL)
+ {
+ g_printerr ("Failed to connect to the D-BUS daemon: %s\n",
+ error.message);
+ dbus_error_free (&error);
+ return NULL;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE);
+
+ _g_dbus_connection_integrate_with_main (dbus_conn);
+
+ dbus_bus_add_match (dbus_conn,
+ "type='signal',sender='" DBUS_SERVICE_DBUS "',"
+ "interface='" DBUS_INTERFACE_DBUS "',"
+ "member='NameOwnerChanged',"
+ "arg0='"G_VFS_DBUS_DAEMON_NAME"'",
+ NULL);
+ dbus_connection_add_filter (dbus_conn,
+ dbus_filter_func,
+ NULL,
+ NULL);
+
+ message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE);
+ dbus_message_set_auto_start (message, TRUE);
+ dbus_connection_send (dbus_conn, message, NULL);
+ dbus_connection_flush (dbus_conn);
+
+ gvfs = g_vfs_get_default ();
+
+ volume_monitor = g_object_new (g_type_from_name ("GDaemonVolumeMonitor"), NULL);
+
+ subthread_main_loop = g_main_loop_new (NULL, FALSE);
+ subthread = g_thread_create ((GThreadFunc) subthread_main, NULL, FALSE, NULL);
+
+ return NULL;
+}
+
+static void
+vfs_destroy (gpointer param)
+{
+ mount_list_free ();
+ if (subthread_main_loop != NULL)
+ g_main_loop_quit (subthread_main_loop);
+ g_mutex_free (mount_list_mutex);
+ g_object_unref (gvfs);
+}
+
+static struct fuse_operations vfs_oper =
+{
+ .init = vfs_init,
+ .destroy = vfs_destroy,
+
+ .getattr = vfs_getattr,
+ .readdir = vfs_readdir,
+
+ .statfs = vfs_statfs,
+
+ .opendir = vfs_opendir,
+ .readdir = vfs_readdir,
+ .readlink = vfs_readlink,
+
+ .open = vfs_open,
+ .create = vfs_create,
+ .release = vfs_release,
+ .flush = vfs_flush,
+
+ .read = vfs_read,
+ .write = vfs_write,
+
+ .rename = vfs_rename,
+ .unlink = vfs_unlink,
+ .mkdir = vfs_mkdir,
+ .rmdir = vfs_rmdir,
+ .ftruncate = vfs_ftruncate,
+ .truncate = vfs_truncate,
+ .symlink = vfs_symlink,
+ .access = vfs_access,
+ .utimens = vfs_utimens,
+ .chmod = vfs_chmod,
+
+#if 0
+ .chown = vfs_chown,
+ .setxattr = vfs_setxattr,
+ .getxattr = vfs_getxattr,
+ .listxattr = vfs_listxattr,
+ .removexattr = vfs_removexattr,
+#endif
+};
+
+gint
+main (gint argc, gchar *argv [])
+{
+ g_type_init ();
+ g_thread_init (NULL);
+
+ return fuse_main (argc, argv, &vfs_oper, NULL /* user data */);
+}
diff --git a/trunk/client/gvfsiconloadable.c b/trunk/client/gvfsiconloadable.c
new file mode 100644
index 00000000..1c6d54b4
--- /dev/null
+++ b/trunk/client/gvfsiconloadable.c
@@ -0,0 +1,431 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "gvfsicon.h"
+#include "gvfsiconloadable.h"
+#include "gmounttracker.h"
+#include "gvfsdaemondbus.h"
+#include "gdaemonvfs.h"
+#include "gdaemonfileinputstream.h"
+#include "gvfsdaemonprotocol.h"
+#include "gdbusutils.h"
+
+/* see comment in common/giconvfs.c for why the GLoadableIcon interface is here */
+
+static DBusMessage *
+create_empty_message (GVfsIcon *vfs_icon,
+ const char *op,
+ GMountInfo **mount_info_out,
+ GError **error)
+{
+ DBusMessage *message;
+ GMountInfo *mount_info;
+
+ mount_info = _g_daemon_vfs_get_mount_info_sync (vfs_icon->mount_spec,
+ "/",
+ error);
+
+ if (mount_info == NULL)
+ return NULL;
+
+ if (mount_info_out)
+ *mount_info_out = g_mount_info_ref (mount_info);
+
+ message =
+ dbus_message_new_method_call (mount_info->dbus_id,
+ mount_info->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ op);
+
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(vfs_icon->icon_id), 0);
+
+ g_mount_info_unref (mount_info);
+ return message;
+}
+
+static DBusMessage *
+do_sync_path_call (GVfsIcon *vfs_icon,
+ const char *op,
+ GMountInfo **mount_info_out,
+ DBusConnection **connection_out,
+ GCancellable *cancellable,
+ GError **error,
+ int first_arg_type,
+ ...)
+{
+ DBusMessage *message, *reply;
+ va_list var_args;
+ GError *my_error;
+
+ retry:
+ message = create_empty_message (vfs_icon, op, mount_info_out, error);
+ if (!message)
+ return NULL;
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (message,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+
+
+ my_error = NULL;
+ reply = _g_vfs_daemon_call_sync (message,
+ connection_out,
+ NULL, NULL, NULL,
+ cancellable, &my_error);
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ {
+ if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
+ {
+ g_error_free (my_error);
+ goto retry;
+ }
+ g_propagate_error (error, my_error);
+ }
+
+ return reply;
+}
+
+static GInputStream *
+g_vfs_icon_load (GLoadableIcon *icon,
+ int size,
+ char **type,
+ GCancellable *cancellable,
+ GError **error)
+{
+ DBusConnection *connection;
+ int fd;
+ DBusMessage *reply;
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+
+ reply = do_sync_path_call (G_VFS_ICON (icon),
+ G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ,
+ NULL,
+ &connection,
+ cancellable,
+ error,
+ 0);
+ if (reply == NULL)
+ return NULL;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (reply);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open_icon_for_read"));
+ return NULL;
+ }
+
+ dbus_message_unref (reply);
+
+ fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
+ if (fd == -1)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Didn't get stream file descriptor"));
+ return NULL;
+ }
+
+ return G_INPUT_STREAM (g_daemon_file_input_stream_new (fd, can_seek));
+}
+
+
+typedef void (*AsyncPathCallCallback) (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data);
+
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ GVfsIcon *vfs_icon;
+ char *op;
+ GCancellable *cancellable;
+ DBusMessage *args;
+ AsyncPathCallCallback callback;
+ gpointer callback_data;
+ GDestroyNotify notify;
+} AsyncPathCall;
+
+
+static void
+async_path_call_free (AsyncPathCall *data)
+{
+ if (data->notify)
+ data->notify (data->callback_data);
+
+ if (data->result)
+ g_object_unref (data->result);
+ g_object_unref (data->vfs_icon);
+ g_free (data->op);
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+ if (data->args)
+ dbus_message_unref (data->args);
+ g_free (data);
+}
+
+static void
+async_path_call_done (DBusMessage *reply,
+ DBusConnection *connection,
+ GError *io_error,
+ gpointer _data)
+{
+ AsyncPathCall *data = _data;
+ GSimpleAsyncResult *result;
+
+ if (io_error != NULL)
+ {
+ g_simple_async_result_set_from_error (data->result, io_error);
+ g_simple_async_result_complete (data->result);
+ async_path_call_free (data);
+ }
+ else
+ {
+ result = data->result;
+ g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data);
+ data->result = NULL;
+
+ data->callback (reply, connection,
+ result,
+ data->cancellable,
+ data->callback_data);
+
+ /* Free data here, or later if callback ref:ed the result */
+ g_object_unref (result);
+ }
+}
+
+static void
+do_async_path_call_callback (GMountInfo *mount_info,
+ gpointer _data,
+ GError *error)
+{
+ AsyncPathCall *data = _data;
+ DBusMessage *message;
+ DBusMessageIter arg_source, arg_dest;
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (data->result, error);
+ g_simple_async_result_complete (data->result);
+ async_path_call_free (data);
+ return;
+ }
+
+ message =
+ dbus_message_new_method_call (mount_info->dbus_id,
+ mount_info->object_path,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ data->op);
+
+ _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(data->vfs_icon->icon_id), 0);
+
+ /* Append more args from data->args */
+
+ if (data->args)
+ {
+ dbus_message_iter_init (data->args, &arg_source);
+ dbus_message_iter_init_append (message, &arg_dest);
+
+ _g_dbus_message_iter_copy (&arg_dest, &arg_source);
+ }
+
+ _g_vfs_daemon_call_async (message,
+ async_path_call_done, data,
+ data->cancellable);
+
+ dbus_message_unref (message);
+}
+
+
+static void
+do_async_path_call (GVfsIcon *vfs_icon,
+ const char *op,
+ GCancellable *cancellable,
+ GAsyncReadyCallback op_callback,
+ gpointer op_callback_data,
+ AsyncPathCallCallback callback,
+ gpointer callback_data,
+ GDestroyNotify notify,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+ AsyncPathCall *data;
+
+ data = g_new0 (AsyncPathCall, 1);
+
+ data->result = g_simple_async_result_new (G_OBJECT (vfs_icon),
+ op_callback, op_callback_data,
+ NULL);
+
+ data->vfs_icon = g_object_ref (vfs_icon);
+ data->op = g_strdup (op);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->callback_data = callback_data;
+ data->notify = notify;
+
+ if (first_arg_type != 0)
+ {
+ data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
+ if (data->args == NULL)
+ _g_dbus_oom ();
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (data->args,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+ }
+
+
+ _g_daemon_vfs_get_mount_info_async (vfs_icon->mount_spec,
+ "/",
+ do_async_path_call_callback,
+ data);
+}
+
+typedef struct {
+ GSimpleAsyncResult *result;
+ gboolean can_seek;
+} GetFDData;
+
+static void
+load_async_get_fd_cb (int fd,
+ gpointer callback_data)
+{
+ GetFDData *data = callback_data;
+ GFileInputStream *stream;
+
+ if (fd == -1)
+ {
+ g_simple_async_result_set_error (data->result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Couldn't get stream file descriptor"));
+ }
+ else
+ {
+ stream = g_daemon_file_input_stream_new (fd, data->can_seek);
+ g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref);
+ }
+
+ g_simple_async_result_complete (data->result);
+
+ g_object_unref (data->result);
+ g_free (data);
+}
+
+static void
+load_async_cb (DBusMessage *reply,
+ DBusConnection *connection,
+ GSimpleAsyncResult *result,
+ GCancellable *cancellable,
+ gpointer callback_data)
+{
+ guint32 fd_id;
+ dbus_bool_t can_seek;
+ GetFDData *get_fd_data;
+
+ if (!dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_INVALID))
+ {
+ g_simple_async_result_set_error (result,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid return value from open"));
+ g_simple_async_result_complete (result);
+ return;
+ }
+
+ get_fd_data = g_new0 (GetFDData, 1);
+ get_fd_data->result = g_object_ref (result);
+ get_fd_data->can_seek = can_seek;
+
+ _g_dbus_connection_get_fd_async (connection, fd_id,
+ load_async_get_fd_cb, get_fd_data);
+}
+
+static void
+g_vfs_icon_load_async (GLoadableIcon *icon,
+ int size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ do_async_path_call (G_VFS_ICON (icon),
+ G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ,
+ cancellable,
+ callback, user_data,
+ load_async_cb, NULL, NULL,
+ 0);
+}
+
+static GInputStream *
+g_vfs_icon_load_finish (GLoadableIcon *icon,
+ GAsyncResult *res,
+ char **type,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ gpointer op;
+
+ op = g_simple_async_result_get_op_res_gpointer (simple);
+ if (op)
+ return g_object_ref (op);
+
+ return NULL;
+}
+
+
+static void
+g_vfs_icon_loadable_icon_iface_init (GLoadableIconIface *iface)
+{
+ iface->load = g_vfs_icon_load;
+ iface->load_async = g_vfs_icon_load_async;
+ iface->load_finish = g_vfs_icon_load_finish;
+}
+
+void
+_g_vfs_icon_add_loadable_interface (void)
+{
+ static const GInterfaceInfo g_implement_interface_info = {
+ (GInterfaceInitFunc) g_vfs_icon_loadable_icon_iface_init
+ };
+
+ g_type_add_interface_static (G_VFS_TYPE_ICON, G_TYPE_LOADABLE_ICON, &g_implement_interface_info);
+}
diff --git a/trunk/client/gvfsiconloadable.h b/trunk/client/gvfsiconloadable.h
new file mode 100644
index 00000000..bda7485a
--- /dev/null
+++ b/trunk/client/gvfsiconloadable.h
@@ -0,0 +1,35 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_ICON_LOADABLE_H__
+#define __G_VFS_ICON_LOADABLE_H__
+
+#include <gio/gio.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+void _g_vfs_icon_add_loadable_interface (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_ICON_LOADABLE_H__ */
diff --git a/trunk/client/gvfsurimapper.c b/trunk/client/gvfsurimapper.c
new file mode 100644
index 00000000..9c98347a
--- /dev/null
+++ b/trunk/client/gvfsurimapper.c
@@ -0,0 +1,220 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <gmodule.h>
+#include "gvfsurimapper.h"
+
+G_DEFINE_DYNAMIC_TYPE (GVfsUriMapper, g_vfs_uri_mapper, G_TYPE_OBJECT)
+
+void
+g_vfs_uri_mapper_register (GIOModule *module)
+{
+ g_vfs_uri_mapper_register_type (G_TYPE_MODULE (module));
+}
+
+GVfsUriMountInfo *
+g_vfs_uri_mount_info_new (const char *type)
+{
+ GVfsUriMountInfo *info;
+
+ info = g_new0 (GVfsUriMountInfo, 1);
+ info->keys = g_array_new (TRUE, TRUE, sizeof (GVfsUriMountInfoKey));
+
+ if (type != NULL)
+ g_vfs_uri_mount_info_set (info, "type", type);
+
+ return info;
+}
+
+void
+g_vfs_uri_mount_info_free (GVfsUriMountInfo *info)
+{
+ int i;
+ GVfsUriMountInfoKey *key;
+
+ for (i = 0; i < info->keys->len; i++) {
+ key = &g_array_index (info->keys, GVfsUriMountInfoKey, i);
+
+ g_free (key->key);
+ g_free (key->value);
+ }
+ g_array_free (info->keys, TRUE);
+ g_free (info->path);
+ g_free (info);
+}
+
+static GVfsUriMountInfoKey *
+lookup_key (GVfsUriMountInfo *info,
+ const char *key)
+{
+ int i;
+ GVfsUriMountInfoKey *keyp;
+
+ for (i = 0; i < info->keys->len; i++) {
+ keyp = &g_array_index (info->keys, GVfsUriMountInfoKey, i);
+
+ if (strcmp (keyp->key, key) == 0)
+ return keyp;
+ }
+
+ return NULL;
+}
+
+const char *
+g_vfs_uri_mount_info_get (GVfsUriMountInfo *info,
+ const char *key)
+{
+ GVfsUriMountInfoKey *keyp;
+
+ keyp = lookup_key (info, key);
+
+ if (keyp)
+ return keyp->value;
+
+ return NULL;
+}
+
+void
+g_vfs_uri_mount_info_set_with_len (GVfsUriMountInfo *info,
+ const char *key,
+ const char *value,
+ int value_len)
+{
+ GVfsUriMountInfoKey *keyp;
+ GVfsUriMountInfoKey keyv;
+ char *value_copy;
+
+ if (value_len == -1)
+ value_copy = g_strdup (value);
+ else
+ value_copy = g_strndup (value, value_len);
+
+ keyp = lookup_key (info, key);
+ if (keyp)
+ {
+ g_free (keyp->value);
+ keyp->value = value_copy;
+ }
+ else
+ {
+ keyv.key = g_strdup (key);
+ keyv.value = value_copy;
+ g_array_append_val (info->keys, keyv);
+ }
+}
+
+void
+g_vfs_uri_mount_info_set (GVfsUriMountInfo *info,
+ const char *key,
+ const char *value)
+{
+ g_vfs_uri_mount_info_set_with_len (info, key, value, -1);
+}
+
+
+static void
+g_vfs_uri_mapper_class_finalize (GVfsUriMapperClass *klass)
+{
+}
+
+static void
+g_vfs_uri_mapper_class_init (GVfsUriMapperClass *klass)
+{
+}
+
+static void
+g_vfs_uri_mapper_init (GVfsUriMapper *vfs)
+{
+}
+
+const char * const *
+g_vfs_uri_mapper_get_handled_schemes (GVfsUriMapper *mapper)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ return (* class->get_handled_schemes) (mapper);
+}
+
+
+GVfsUriMountInfo *
+g_vfs_uri_mapper_from_uri (GVfsUriMapper *mapper,
+ const char *uri)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ return (* class->from_uri) (mapper, uri);
+}
+
+GVfsUriMountInfo *
+g_vfs_uri_mapper_get_mount_info_for_path (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info,
+ const char *new_path)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ if (class->get_mount_info_for_path != NULL)
+ return (* class->get_mount_info_for_path) (mapper, info, new_path);
+ else
+ return NULL;
+}
+
+const char * const *
+g_vfs_uri_mapper_get_handled_mount_types (GVfsUriMapper *mapper)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ return (* class->get_handled_mount_types) (mapper);
+}
+
+char *
+g_vfs_uri_mapper_to_uri (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info,
+ gboolean allow_utf8)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ return (* class->to_uri) (mapper, mount_info, allow_utf8);
+}
+
+const char *
+g_vfs_uri_mapper_to_uri_scheme (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info)
+{
+ GVfsUriMapperClass *class;
+
+ class = G_VFS_URI_MAPPER_GET_CLASS (mapper);
+
+ return (* class->to_uri_scheme) (mapper, mount_info);
+}
+
diff --git a/trunk/client/gvfsurimapper.h b/trunk/client/gvfsurimapper.h
new file mode 100644
index 00000000..6a3b5ea5
--- /dev/null
+++ b/trunk/client/gvfsurimapper.h
@@ -0,0 +1,109 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_URI_MAPPER_H__
+#define __G_VFS_URI_MAPPER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_URI_MAPPER (g_vfs_uri_mapper_get_type ())
+#define G_VFS_URI_MAPPER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_URI_MAPPER, GVfsUriMapper))
+#define G_VFS_URI_MAPPER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_URI_MAPPER, GVfsUriMapperClass))
+#define G_VFS_URI_MAPPER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_URI_MAPPER, GVfsUriMapperClass))
+#define G_IS_VFS_URI_MAPPER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_URI_MAPPER))
+#define G_IS_VFS_URI_MAPPER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_URI_MAPPER))
+
+typedef struct _GVfsUriMapper GVfsUriMapper; /* Dummy typedef */
+typedef struct _GVfsUriMapperClass GVfsUriMapperClass;
+
+struct _GVfsUriMapper {
+ GObject parent;
+};
+
+/* Keep in sync with GMountSpecItem */
+typedef struct {
+ char *key;
+ char *value;
+} GVfsUriMountInfoKey;
+
+typedef struct {
+ GArray *keys;
+ char *path;
+} GVfsUriMountInfo;
+
+struct _GVfsUriMapperClass
+{
+ GObjectClass parent_class;
+
+ /* Virtual Table */
+
+ const char * const * (*get_handled_schemes) (GVfsUriMapper *mapper);
+ GVfsUriMountInfo * (*from_uri) (GVfsUriMapper *mapper,
+ const char *uri);
+ GVfsUriMountInfo * (*get_mount_info_for_path) (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info,
+ const char *new_path);
+
+ const char * const * (*get_handled_mount_types) (GVfsUriMapper *mapper);
+ char * (*to_uri) (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info,
+ gboolean allow_utf8);
+ const char * (*to_uri_scheme) (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info);
+};
+
+GType g_vfs_uri_mapper_get_type (void);
+void g_vfs_uri_mapper_register (GIOModule *module);
+
+GVfsUriMountInfo *g_vfs_uri_mount_info_new (const char *type);
+void g_vfs_uri_mount_info_free (GVfsUriMountInfo *info);
+const char * g_vfs_uri_mount_info_get (GVfsUriMountInfo *info,
+ const char *key);
+void g_vfs_uri_mount_info_set (GVfsUriMountInfo *info,
+ const char *key,
+ const char *value);
+void g_vfs_uri_mount_info_set_with_len (GVfsUriMountInfo *info,
+ const char *key,
+ const char *value,
+ int value_len);
+
+const char * const *g_vfs_uri_mapper_get_handled_schemes (GVfsUriMapper *mapper);
+GVfsUriMountInfo * g_vfs_uri_mapper_from_uri (GVfsUriMapper *mapper,
+ const char *uri);
+GVfsUriMountInfo * g_vfs_uri_mapper_get_mount_info_for_path (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info,
+ const char *new_path);
+
+const char * const *g_vfs_uri_mapper_get_handled_mount_types (GVfsUriMapper *mapper);
+char * g_vfs_uri_mapper_to_uri (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_info,
+ gboolean allow_utf8);
+const char * g_vfs_uri_mapper_to_uri_scheme (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *mount_infoxo);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_URI_MAPPER_H__ */
diff --git a/trunk/client/gvfsuriutils.c b/trunk/client/gvfsuriutils.c
new file mode 100644
index 00000000..206d5a7e
--- /dev/null
+++ b/trunk/client/gvfsuriutils.c
@@ -0,0 +1,291 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include "gvfsuriutils.h"
+#include <string.h>
+#include <stdlib.h>
+
+void
+g_vfs_decoded_uri_free (GDecodedUri *decoded)
+{
+ if (decoded == NULL)
+ return;
+
+ g_free (decoded->scheme);
+ g_free (decoded->query);
+ g_free (decoded->fragment);
+ g_free (decoded->userinfo);
+ g_free (decoded->host);
+ g_free (decoded->path);
+ g_free (decoded);
+}
+
+GDecodedUri *
+g_vfs_decoded_uri_new (void)
+{
+ GDecodedUri *uri;
+
+ uri = g_new0 (GDecodedUri, 1);
+ uri->port = -1;
+
+ return uri;
+}
+
+GDecodedUri *
+g_vfs_decode_uri (const char *uri)
+{
+ GDecodedUri *decoded;
+ const char *p, *in, *hier_part_start, *hier_part_end, *query_start, *fragment_start;
+ char *out;
+ char c;
+
+ /* From RFC 3986 Decodes:
+ * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ */
+
+ p = uri;
+
+ /* Decode scheme:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+
+ if (!g_ascii_isalpha (*p))
+ return NULL;
+
+ while (1)
+ {
+ c = *p++;
+
+ if (c == ':')
+ break;
+
+ if (!(g_ascii_isalnum(c) ||
+ c == '+' ||
+ c == '-' ||
+ c == '.'))
+ return NULL;
+ }
+
+ decoded = g_vfs_decoded_uri_new ();
+
+ decoded->scheme = g_malloc (p - uri);
+ out = decoded->scheme;
+ for (in = uri; in < p - 1; in++)
+ *out++ = g_ascii_tolower (*in);
+ *out = 0;
+
+ hier_part_start = p;
+
+ query_start = strchr (p, '?');
+ if (query_start)
+ {
+ hier_part_end = query_start++;
+ fragment_start = strchr (query_start, '#');
+ if (fragment_start)
+ {
+ decoded->query = g_strndup (query_start, fragment_start - query_start);
+ decoded->fragment = g_strdup (fragment_start+1);
+ }
+ else
+ {
+ decoded->query = g_strdup (query_start);
+ decoded->fragment = NULL;
+ }
+ }
+ else
+ {
+ /* No query */
+ decoded->query = NULL;
+ fragment_start = strchr (p, '#');
+ if (fragment_start)
+ {
+ hier_part_end = fragment_start++;
+ decoded->fragment = g_strdup (fragment_start);
+ }
+ else
+ {
+ hier_part_end = p + strlen (p);
+ decoded->fragment = NULL;
+ }
+ }
+
+ /* 3:
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ */
+
+ if (hier_part_start[0] == '/' &&
+ hier_part_start[1] == '/')
+ {
+ const char *authority_start, *authority_end;
+ const char *userinfo_start, *userinfo_end;
+ const char *host_start, *host_end;
+ const char *port_start;
+
+ authority_start = hier_part_start + 2;
+ /* authority is always followed by / or nothing */
+ authority_end = memchr (authority_start, '/', hier_part_end - authority_start);
+ if (authority_end == NULL)
+ authority_end = hier_part_end;
+
+ /* 3.2:
+ authority = [ userinfo "@" ] host [ ":" port ]
+ */
+
+ userinfo_end = memchr (authority_start, '@', authority_end - authority_start);
+ if (userinfo_end)
+ {
+ userinfo_start = authority_start;
+ decoded->userinfo = g_uri_unescape_segment (userinfo_start, userinfo_end, NULL);
+ if (decoded->userinfo == NULL)
+ {
+ g_vfs_decoded_uri_free (decoded);
+ return NULL;
+ }
+ host_start = userinfo_end + 1;
+ }
+ else
+ host_start = authority_start;
+
+ /* We should handle hostnames in brackets, as those are used by IPv6 URIs
+ * See http://tools.ietf.org/html/rfc2732 */
+ if (*host_start == '[')
+ {
+ char *s;
+
+ port_start = NULL;
+ host_end = memchr (host_start, ']', authority_end - host_start);
+ if (host_end == NULL)
+ {
+ g_vfs_decoded_uri_free (decoded);
+ return NULL;
+ }
+
+ /* Look for the start of the port,
+ * And we sure we don't have it start somewhere
+ * in the path section */
+ s = (char *) host_end;
+ while (1)
+ {
+ if (*s == '/')
+ {
+ port_start = NULL;
+ break;
+ }
+ else if (*s == ':')
+ {
+ port_start = s;
+ break;
+ }
+ else if (*s == '\0')
+ {
+ break;
+ }
+
+ s++;
+ }
+ }
+ else
+ {
+ port_start = memchr (host_start, ':', authority_end - host_start);
+ }
+
+ if (port_start)
+ {
+ host_end = port_start++;
+
+ decoded->port = atoi(port_start);
+ }
+ else
+ {
+ host_end = authority_end;
+ decoded->port = -1;
+ }
+
+ decoded->host = g_uri_unescape_segment (host_start, host_end, NULL);
+
+ hier_part_start = authority_end;
+ }
+
+ decoded->path = g_uri_unescape_segment (hier_part_start, hier_part_end, "/");
+
+ if (decoded->path == NULL)
+ {
+ g_vfs_decoded_uri_free (decoded);
+ return NULL;
+ }
+
+ return decoded;
+}
+
+char *
+g_vfs_encode_uri (GDecodedUri *decoded, gboolean allow_utf8)
+{
+ GString *uri;
+
+ uri = g_string_new (NULL);
+
+ g_string_append (uri, decoded->scheme);
+ g_string_append (uri, "://");
+
+ if (decoded->host != NULL)
+ {
+ if (decoded->userinfo)
+ {
+ /* userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) */
+ g_string_append_uri_escaped (uri, decoded->userinfo,
+ G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, allow_utf8);
+ g_string_append_c (uri, '@');
+ }
+
+ g_string_append_uri_escaped (uri, decoded->host,
+ /* Allowed unescaped in hostname / ip address */
+ G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS ":[]" ,
+ allow_utf8);
+
+ if (decoded->port != -1)
+ {
+ g_string_append_c (uri, ':');
+ g_string_append_printf (uri, "%d", decoded->port);
+ }
+ }
+
+ g_string_append_uri_escaped (uri, decoded->path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, allow_utf8);
+
+ if (decoded->query)
+ {
+ g_string_append_c (uri, '?');
+ g_string_append (uri, decoded->query);
+ }
+
+ if (decoded->fragment)
+ {
+ g_string_append_c (uri, '#');
+ g_string_append (uri, decoded->fragment);
+ }
+
+ return g_string_free (uri, FALSE);
+}
diff --git a/trunk/client/gvfsuriutils.h b/trunk/client/gvfsuriutils.h
new file mode 100644
index 00000000..15550464
--- /dev/null
+++ b/trunk/client/gvfsuriutils.h
@@ -0,0 +1,49 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_URI_UTILS_H__
+#define __G_VFS_URI_UTILS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+ char *scheme;
+ char *userinfo;
+ char *host;
+ int port; /* -1 => not in uri */
+ char *path;
+ char *query;
+ char *fragment;
+} GDecodedUri;
+
+char * g_vfs_encode_uri (GDecodedUri *decoded,
+ gboolean allow_utf8);
+void g_vfs_decoded_uri_free (GDecodedUri *decoded);
+GDecodedUri *g_vfs_decode_uri (const char *uri);
+GDecodedUri *g_vfs_decoded_uri_new (void);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_URI_UTILS_H__ */
diff --git a/trunk/client/httpuri.c b/trunk/client/httpuri.c
new file mode 100644
index 00000000..03f7fb68
--- /dev/null
+++ b/trunk/client/httpuri.c
@@ -0,0 +1,294 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <stdlib.h> /* atoi */
+
+#include <gio/gio.h>
+#include <gvfsurimapper.h>
+#include <gvfsuriutils.h>
+
+typedef struct _GVfsUriMapperHttp GVfsUriMapperHttp;
+typedef struct _GVfsUriMapperHttpClass GVfsUriMapperHttpClass;
+
+struct _GVfsUriMapperHttp
+{
+ GVfsUriMapper parent;
+};
+
+struct _GVfsUriMapperHttpClass
+{
+ GVfsUriMapperClass parent_class;
+};
+
+GType g_vfs_uri_mapper_http_get_type (void);
+void g_vfs_uri_mapper_http_register (GIOModule *module);
+
+G_DEFINE_DYNAMIC_TYPE (GVfsUriMapperHttp, g_vfs_uri_mapper_http, G_VFS_TYPE_URI_MAPPER)
+
+static void
+g_vfs_uri_mapper_http_init (GVfsUriMapperHttp *vfs)
+{
+}
+
+static const char * const *
+http_get_handled_schemes (GVfsUriMapper *mapper)
+{
+ static const char *schemes[] = {
+ "http",
+ "https",
+ "dav",
+ "davs",
+ NULL
+ };
+ return schemes;
+}
+
+static inline gboolean
+port_is_defaul_port (int port, gboolean ssl)
+{
+ if (ssl)
+ return port == 443;
+ else
+ return port == 80;
+}
+
+static GVfsUriMountInfo *
+http_from_uri (GVfsUriMapper *mapper,
+ const char *uri_str)
+{
+ GVfsUriMountInfo *info;
+ gboolean ssl;
+ GDecodedUri *uri;
+
+ uri = g_vfs_decode_uri (uri_str);
+
+ if (uri == NULL)
+ return NULL;
+
+ if (!g_ascii_strncasecmp (uri->scheme, "http", 4))
+ {
+ info = g_vfs_uri_mount_info_new ("http");
+ g_vfs_uri_mount_info_set (info, "uri", uri_str);
+ }
+ else
+ {
+ info = g_vfs_uri_mount_info_new ("dav");
+ ssl = !g_ascii_strcasecmp (uri->scheme, "davs");
+ g_vfs_uri_mount_info_set (info, "ssl", ssl ? "true" : "false");
+
+ if (uri->host && *uri->host)
+ g_vfs_uri_mount_info_set (info, "host", uri->host);
+
+ if (uri->userinfo && *uri->userinfo)
+ g_vfs_uri_mount_info_set (info, "user", uri->userinfo);
+
+ /* only set the port if it isn't the default port */
+ if (uri->port != -1 && ! port_is_defaul_port (uri->port, ssl))
+ {
+ char *port = g_strdup_printf ("%d", uri->port);
+ g_vfs_uri_mount_info_set (info, "port", port);
+ g_free (port);
+ }
+ }
+
+ info->path = uri->path;
+ uri->path = NULL;
+ g_vfs_decoded_uri_free (uri);
+
+ return info;
+}
+
+static GVfsUriMountInfo *
+http_get_mount_info_for_path (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info,
+ const char *new_path)
+{
+ const char *type;
+
+ type = g_vfs_uri_mount_info_get (info, "type");
+
+ if (strcmp (type, "http") == 0)
+ {
+ const char *uri_str;
+ char *new_uri;
+ GDecodedUri *uri;
+ GVfsUriMountInfo *new_info;
+
+ uri_str = g_vfs_uri_mount_info_get (info, "uri");
+
+ uri = g_vfs_decode_uri (uri_str);
+
+ if (uri == NULL)
+ return NULL;
+
+ if (strcmp (uri->path, new_path) == 0)
+ {
+ g_vfs_decoded_uri_free (uri);
+ return NULL;
+ }
+
+ g_free (uri->path);
+ uri->path = g_strdup (new_path);
+
+ g_free (uri->query);
+ uri->query = NULL;
+
+ g_free (uri->fragment);
+ uri->fragment = NULL;
+
+ new_info = g_vfs_uri_mount_info_new ("http");
+
+ new_uri = g_vfs_encode_uri (uri, TRUE);
+ g_vfs_uri_mount_info_set (new_info, "uri", new_uri);
+ g_free (new_uri);
+
+ g_vfs_decoded_uri_free (uri);
+
+ return new_info;
+ }
+ else
+ return NULL;
+}
+
+static const char * const *
+http_get_handled_mount_types (GVfsUriMapper *mapper)
+{
+ static const char *types[] = {
+ "http",
+ "dav",
+ NULL
+ };
+ return types;
+}
+
+static char *
+http_to_uri (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info,
+ gboolean allow_utf8)
+{
+ char *res;
+ const char *type;
+ const char *host;
+ const char *user;
+ const char *port;
+ const char *ssl;
+
+ type = g_vfs_uri_mount_info_get (info, "type");
+
+ if (strcmp (type, "http") == 0)
+ {
+ res = g_strdup (g_vfs_uri_mount_info_get (info, "uri"));
+ }
+ else
+ {
+ GDecodedUri *decoded_uri;
+ int port_num;
+
+ decoded_uri = g_new0 (GDecodedUri, 1);
+
+ ssl = g_vfs_uri_mount_info_get (info, "ssl");
+ host = g_vfs_uri_mount_info_get (info, "host");
+ user = g_vfs_uri_mount_info_get (info, "user");
+ port = g_vfs_uri_mount_info_get (info, "port");
+
+ if (ssl && strcmp (ssl, "true") == 0)
+ decoded_uri->scheme = g_strdup ("davs");
+ else
+ decoded_uri->scheme = g_strdup ("dav");
+
+ decoded_uri->host = g_strdup (host);
+ decoded_uri->userinfo = g_strdup (user);
+
+ if (port && (port_num = atoi (port)))
+ decoded_uri->port = port_num;
+ else
+ decoded_uri->port = -1;
+
+ decoded_uri->path = g_strdup (info->path);
+
+ res = g_vfs_encode_uri (decoded_uri, allow_utf8);
+ g_vfs_decoded_uri_free (decoded_uri);
+ }
+
+ return res;
+}
+
+static const char *
+http_to_uri_scheme (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info)
+{
+ const gchar *ssl;
+ const gchar *type;
+ gboolean is_dav;
+ gboolean is_ssl;
+
+ ssl = g_vfs_uri_mount_info_get (info, "ssl");
+ type = g_vfs_uri_mount_info_get (info, "type");
+
+ if (strcmp (type, "dav") == 0)
+ is_dav = TRUE;
+ else if (strcmp (type, "http") == 0)
+ is_dav = FALSE;
+ else
+ return NULL;
+
+ is_ssl =
+ ssl != NULL &&
+ strcmp (ssl, "true") == 0;
+
+ if (is_dav && is_ssl)
+ return "davs";
+ else if (is_dav && !is_ssl)
+ return "dav";
+ else if (!is_dav && is_ssl)
+ return "https";
+ else
+ return "http";
+}
+
+static void
+g_vfs_uri_mapper_http_class_finalize (GVfsUriMapperHttpClass *klass)
+{
+}
+
+static void
+g_vfs_uri_mapper_http_class_init (GVfsUriMapperHttpClass *class)
+{
+ GVfsUriMapperClass *mapper_class;
+
+ mapper_class = G_VFS_URI_MAPPER_CLASS (class);
+ mapper_class->get_handled_schemes = http_get_handled_schemes;
+ mapper_class->from_uri = http_from_uri;
+ mapper_class->get_mount_info_for_path = http_get_mount_info_for_path;
+ mapper_class->get_handled_mount_types = http_get_handled_mount_types;
+ mapper_class->to_uri = http_to_uri;
+ mapper_class->to_uri_scheme = http_to_uri_scheme;
+}
+
+void
+g_vfs_uri_mapper_http_register (GIOModule *module)
+{
+ g_vfs_uri_mapper_http_register_type (G_TYPE_MODULE (module));
+}
diff --git a/trunk/client/smburi.c b/trunk/client/smburi.c
new file mode 100644
index 00000000..d3804cf4
--- /dev/null
+++ b/trunk/client/smburi.c
@@ -0,0 +1,297 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <gio/gio.h>
+#include <gvfsurimapper.h>
+#include <gvfsuriutils.h>
+
+typedef struct _GVfsUriMapperSmb GVfsUriMapperSmb;
+typedef struct _GVfsUriMapperSmbClass GVfsUriMapperSmbClass;
+
+struct _GVfsUriMapperSmb
+{
+ GVfsUriMapper parent;
+};
+
+struct _GVfsUriMapperSmbClass
+{
+ GVfsUriMapperClass parent_class;
+};
+
+GType g_vfs_uri_mapper_smb_get_type (void);
+void g_vfs_uri_mapper_smb_register (GIOModule *module);
+
+G_DEFINE_DYNAMIC_TYPE (GVfsUriMapperSmb, g_vfs_uri_mapper_smb, G_VFS_TYPE_URI_MAPPER)
+
+static void
+g_vfs_uri_mapper_smb_init (GVfsUriMapperSmb *vfs)
+{
+}
+
+static char *
+normalize_smb_name (const char *name, gssize len)
+{
+ gboolean valid_utf8;
+
+ valid_utf8 = g_utf8_validate (name, len, NULL);
+
+ if (valid_utf8)
+ return g_utf8_casefold (name, len);
+ else
+ return g_ascii_strdown (name, len);
+}
+
+static const char * const *
+smb_get_handled_schemes (GVfsUriMapper *mapper)
+{
+ static const char *schemes[] = {
+ "smb",
+ NULL
+ };
+ return schemes;
+}
+
+static GVfsUriMountInfo *
+smb_from_uri (GVfsUriMapper *mapper,
+ const char *uri_str)
+{
+ char *tmp;
+ const char *p;
+ const char *share, *share_end;
+ GDecodedUri *uri;
+ GVfsUriMountInfo *info;
+
+ uri = g_vfs_decode_uri (uri_str);
+ if (uri == NULL)
+ return NULL;
+
+ if (uri->host == NULL || strlen (uri->host) == 0)
+ {
+ /* uri form: smb:/// or smb:///$path */
+ info = g_vfs_uri_mount_info_new ("smb-network");
+ if (uri->path == NULL || *uri->path == 0)
+ info->path = g_strdup ("/");
+ else
+ info->path = g_strdup (uri->path);
+ }
+ else
+ {
+ /* host set */
+ p = uri->path;
+ while (p && *p == '/')
+ p++;
+
+ if (p == NULL || *p == 0)
+ {
+ /* uri form: smb://$host/ */
+ info = g_vfs_uri_mount_info_new ("smb-server");
+ tmp = normalize_smb_name (uri->host, -1);
+ g_vfs_uri_mount_info_set (info, "server", tmp);
+ g_free (tmp);
+ info->path = g_strdup ("/");
+ }
+ else
+ {
+ share = p;
+ share_end = strchr (share, '/');
+ if (share_end == NULL)
+ share_end = share + strlen (share);
+
+ p = share_end;
+
+ while (*p == '/')
+ p++;
+
+ if (*p == 0)
+ {
+ /* uri form: smb://$host/$share/
+ * Here we special case smb-server files by adding "._" to the names in the uri */
+ if (share[0] == '.' && share[1] == '_')
+ {
+ info = g_vfs_uri_mount_info_new ("smb-server");
+ tmp = normalize_smb_name (uri->host, -1);
+ g_vfs_uri_mount_info_set (info, "server", tmp);
+ g_free (tmp);
+ tmp = normalize_smb_name (share + 2, share_end - (share + 2));
+ info->path = g_strconcat ("/", tmp, NULL);
+ g_free (tmp);
+ }
+ else
+ {
+ info = g_vfs_uri_mount_info_new ("smb-share");
+ tmp = normalize_smb_name (uri->host, -1);
+ g_vfs_uri_mount_info_set (info, "server", tmp);
+ g_free (tmp);
+ tmp = normalize_smb_name (share, share_end - share);
+ g_vfs_uri_mount_info_set (info, "share", tmp);
+ g_free (tmp);
+ info->path = g_strdup ("/");
+ }
+ }
+ else
+ {
+ info = g_vfs_uri_mount_info_new ("smb-share");
+
+ tmp = normalize_smb_name (uri->host, -1);
+ g_vfs_uri_mount_info_set (info, "server", tmp);
+ g_free (tmp);
+
+ tmp = normalize_smb_name (share, share_end - share);
+ g_vfs_uri_mount_info_set (info, "share", tmp);
+ g_free (tmp);
+
+ info->path = g_strconcat ("/", p, NULL);
+ }
+ }
+ }
+
+ if (uri->userinfo)
+ {
+ const char *user = uri->userinfo;
+ p = strchr (uri->userinfo, ';');
+ if (p)
+ {
+ if (p != user)
+ g_vfs_uri_mount_info_set_with_len (info, "domain", user, p - user);
+ user = p + 1;
+ }
+ if (*user != 0)
+ g_vfs_uri_mount_info_set (info, "user", user);
+ }
+
+ g_vfs_decoded_uri_free (uri);
+
+ return info;
+}
+
+static const char * const *
+smb_get_handled_mount_types (GVfsUriMapper *mapper)
+{
+ static const char *types[] = {
+ "smb-network",
+ "smb-server",
+ "smb-share",
+ NULL
+ };
+ return types;
+}
+
+static char *
+smb_to_uri (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info,
+ gboolean allow_utf8)
+{
+ const char *type;
+ const char *server;
+ const char *share;
+ const char *user;
+ const char *domain;
+ char *s;
+ GDecodedUri *uri;
+
+ uri = g_new0 (GDecodedUri, 1);
+
+ type = g_vfs_uri_mount_info_get (info, "type");
+
+ uri->scheme = g_strdup ("smb");
+ uri->port = -1;
+
+ if (strcmp (type, "smb-network") == 0)
+ {
+ uri->path = g_strdup (info->path);
+ }
+ else if (strcmp (type, "smb-server") == 0)
+ {
+ server = g_vfs_uri_mount_info_get (info, "server");
+ uri->host = g_strdup (server);
+
+ /* Map the mountables in server to ._share because the actual share mount maps to smb://server/share */
+ if (info->path && info->path[0] == '/' && info->path[1] != 0)
+ uri->path = g_strconcat ("/._", info->path + 1, NULL);
+ else
+ uri->path = g_strdup ("/");
+ }
+ else if (strcmp (type, "smb-share") == 0)
+ {
+ server = g_vfs_uri_mount_info_get (info, "server");
+ uri->host = g_strdup (server);
+ share = g_vfs_uri_mount_info_get (info, "share");
+ if (info->path[0] == '/')
+ uri->path = g_strconcat ("/", share, info->path, NULL);
+ else
+ uri->path = g_strconcat ("/", share, "/", info->path, NULL);
+
+ user = g_vfs_uri_mount_info_get (info, "user");
+ domain = g_vfs_uri_mount_info_get (info, "domain");
+ if (user) {
+ if (domain)
+ uri->userinfo = g_strconcat (domain, ";", user, NULL);
+ else
+ uri->userinfo = g_strdup (user);
+ }
+ }
+
+ s = g_vfs_encode_uri (uri, allow_utf8);
+ g_vfs_decoded_uri_free (uri);
+ return s;
+}
+
+static const char *
+smb_to_uri_scheme (GVfsUriMapper *mapper,
+ GVfsUriMountInfo *info)
+{
+ const gchar *type = g_vfs_uri_mount_info_get (info, "type");
+
+ if (strcmp ("smb-network", type) == 0 ||
+ strcmp ("smb-server", type) == 0 ||
+ strcmp ("smb-share", type) == 0)
+ return "smb";
+ else
+ return NULL;
+}
+
+static void
+g_vfs_uri_mapper_smb_class_finalize (GVfsUriMapperSmbClass *klass)
+{
+}
+
+static void
+g_vfs_uri_mapper_smb_class_init (GVfsUriMapperSmbClass *class)
+{
+ GVfsUriMapperClass *mapper_class;
+
+ mapper_class = G_VFS_URI_MAPPER_CLASS (class);
+ mapper_class->get_handled_schemes = smb_get_handled_schemes;
+ mapper_class->from_uri = smb_from_uri;
+ mapper_class->get_handled_mount_types = smb_get_handled_mount_types;
+ mapper_class->to_uri = smb_to_uri;
+ mapper_class->to_uri_scheme = smb_to_uri_scheme;
+}
+
+void
+g_vfs_uri_mapper_smb_register (GIOModule *module)
+{
+ g_vfs_uri_mapper_smb_register_type (G_TYPE_MODULE (module));
+}
diff --git a/trunk/client/test-uri-utils.c b/trunk/client/test-uri-utils.c
new file mode 100644
index 00000000..4d21f165
--- /dev/null
+++ b/trunk/client/test-uri-utils.c
@@ -0,0 +1,60 @@
+
+#include <string.h>
+
+#include "gvfsuriutils.h"
+
+
+typedef struct {
+ const char *uri;
+ const char *expected_host;
+ guint expected_port;
+} TestURIs;
+
+static TestURIs uris[] = {
+ { "https://[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:443/", "[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]", 443 },
+ { "http://test:443/", "test", 443 },
+ { "http://test/", "test", -1 },
+ { "obex://[00:FF:FF:FF:FF:FF]/MMC/foo.jpg", "[00:FF:FF:FF:FF:FF]", -1 },
+ { "obex://[00:FF:FF:FF:FF:FF]/C:", "[00:FF:FF:FF:FF:FF]", -1 },
+ { "http://windows-host:8080/C:/", "windows-host", 8080 },
+ { "smb://user:password@192.192.192.192/foobar", "192.192.192.192", -1 },
+ { "https://d134w4tst3t.s3.amazonaws.com/a?Signature=6VJ9%2BAdPVZ4Z7NnPShRvtDsLofc%3D&Expires=1249330377&AWSAccessKeyId=0EYZF4DV8A7WM0H73602", "d134w4tst3t.s3.amazonaws.com", -1 },
+};
+
+int main (int argc, char **argv)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (uris); i++) {
+ GDecodedUri *decoded;
+ char *encoded;
+
+ decoded = g_vfs_decode_uri (uris[i].uri);
+ if (decoded == NULL) {
+ g_warning ("Failed to parse \"%s\"", uris[i].uri);
+ return 1;
+ }
+ if (decoded->host == NULL || strcmp (decoded->host, uris[i].expected_host) != 0) {
+ g_warning ("Wrong host for \"%s\" (got '%s', expected '%s')", uris[i].uri, decoded->host, uris[i].expected_host);
+ g_vfs_decoded_uri_free (decoded);
+ return 1;
+ }
+ if (decoded->port != uris[i].expected_port) {
+ g_warning ("Wrong port for \"%s\"", uris[i].uri);
+ g_vfs_decoded_uri_free (decoded);
+ return 1;
+ }
+ encoded = g_vfs_encode_uri (decoded, TRUE);
+ if (encoded == NULL || strcmp (encoded, uris[i].uri) != 0) {
+ g_warning ("Failed to re-encode \"%s\" from '%s'", uris[i].uri, encoded);
+ g_vfs_decoded_uri_free (decoded);
+ g_free (encoded);
+ return 1;
+ }
+ g_free (encoded);
+ g_vfs_decoded_uri_free (decoded);
+ }
+
+ return 0;
+}
+
diff --git a/trunk/common/Makefile.am b/trunk/common/Makefile.am
new file mode 100644
index 00000000..35d6f2d0
--- /dev/null
+++ b/trunk/common/Makefile.am
@@ -0,0 +1,47 @@
+NULL =
+
+lib_LTLIBRARIES=libgvfscommon.la
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \
+ -I$(top_srcdir)/daemon \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \
+ -DDBUS_API_SUBJECT_TO_CHANGE
+
+libgvfscommon_la_SOURCES = \
+ gsysutils.c gsysutils.h \
+ gdbusutils.c gdbusutils.h \
+ gmountspec.c gmountspec.h \
+ gmountoperationdbus.c gmountoperationdbus.h \
+ gmountsource.c gmountsource.h \
+ gmounttracker.c gmounttracker.h \
+ gvfsdaemonprotocol.c gvfsdaemonprotocol.h \
+ gvfsicon.h gvfsicon.c \
+ gvfsmountinfo.h gvfsmountinfo.c \
+ gvfsfileinfo.c gvfsfileinfo.h \
+ $(NULL)
+
+# needed by cygwin (see bug #564003)
+libgvfscommon_la_LDFLAGS = -no-undefined
+
+libgvfscommon_la_LIBADD = \
+ $(DBUS_LIBS) \
+ $(GLIB_LIBS)
+
+if HAVE_AVAHI
+lib_LTLIBRARIES += libgvfscommon-dnssd.la
+
+libgvfscommon_dnssd_la_SOURCES = \
+ gvfsdnssdutils.c gvfsdnssdutils.h \
+ gvfsdnssdresolver.c gvfsdnssdresolver.h \
+ $(NULL)
+
+libgvfscommon_dnssd_la_CFLAGS = \
+ $(AVAHI_CFLAGS)
+
+libgvfscommon_dnssd_la_LIBADD = \
+ libgvfscommon.la \
+ $(AVAHI_LIBS) \
+ $(GLIB_LIBS)
+endif
+
diff --git a/trunk/common/gdbusutils.c b/trunk/common/gdbusutils.c
new file mode 100644
index 00000000..c3f3f332
--- /dev/null
+++ b/trunk/common/gdbusutils.c
@@ -0,0 +1,1334 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+
+void
+_g_dbus_oom (void)
+{
+ g_error ("DBus failed with out of memory error");
+}
+
+/* We use _ for escaping, so its not valid */
+#define VALID_INITIAL_NAME_CHARACTER(c) \
+ ( ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') )
+#define VALID_NAME_CHARACTER(c) \
+ ( ((c) >= '0' && (c) <= '9') || \
+ ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z'))
+
+
+static void
+append_escaped_name (GString *s,
+ const char *unescaped)
+{
+ char c;
+ gboolean first;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ first = TRUE;
+ while ((c = *unescaped++) != 0)
+ {
+ if (first)
+ {
+ if (VALID_INITIAL_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+ else
+ {
+ if (VALID_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+
+ first = FALSE;
+ g_string_append_c (s, '_');
+ g_string_append_c (s, hex[((guchar)c) >> 4]);
+ g_string_append_c (s, hex[((guchar)c) & 0xf]);
+ }
+}
+
+DBusMessage *
+_dbus_message_new_gerror (DBusMessage *message,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...)
+{
+ DBusMessage *reply;
+ va_list args;
+ GError error;
+
+ error.domain = domain;
+ error.code = code;
+ va_start (args, format);
+ error.message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ reply = _dbus_message_new_from_gerror (message, &error);
+
+ g_free (error.message);
+
+ return reply;
+}
+
+DBusMessage *
+_dbus_message_new_from_gerror (DBusMessage *message,
+ GError *error)
+{
+ DBusMessage *reply;
+ GString *str;
+
+ str = g_string_new ("org.glib.GError.");
+ append_escaped_name (str, g_quark_to_string (error->domain));
+ g_string_append_printf (str, ".c%d", error->code);
+ reply = dbus_message_new_error (message, str->str, error->message);
+ g_string_free (str, TRUE);
+ return reply;
+}
+
+gboolean
+_g_error_from_message (DBusMessage *message,
+ GError **error)
+{
+ DBusError derror;
+
+ dbus_error_init (&derror);
+ if (dbus_set_error_from_message (&derror, message))
+ {
+ _g_error_from_dbus (&derror, error);
+ dbus_error_free (&derror);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+static void
+append_unescaped_dbus_name (GString *s,
+ const char *escaped,
+ const char *end)
+{
+ guchar c;
+
+ while (escaped < end)
+ {
+ c = *escaped++;
+ if (c == '_' &&
+ escaped < end)
+ {
+ c = g_ascii_xdigit_value (*escaped++) << 4;
+
+ if (escaped < end)
+ c |= g_ascii_xdigit_value (*escaped++);
+ }
+ g_string_append_c (s, c);
+ }
+}
+
+void
+_g_dbus_message_iter_append_cstring (DBusMessageIter *iter, const char *str)
+{
+ DBusMessageIter array;
+
+ if (str == NULL)
+ str = "";
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_fixed_array (&array,
+ DBUS_TYPE_BYTE,
+ &str, strlen (str)))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &array))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_message_iter_append_args_valist (DBusMessageIter *iter,
+ int first_arg_type,
+ va_list var_args)
+{
+ int type;
+
+ g_return_if_fail (iter != NULL);
+
+ type = first_arg_type;
+
+ while (type != DBUS_TYPE_INVALID)
+ {
+ if (type == G_DBUS_TYPE_CSTRING)
+ {
+ const char **value_p;
+ const char *value;
+
+ value_p = va_arg (var_args, const char**);
+ value = *value_p;
+
+ _g_dbus_message_iter_append_cstring (iter, value);
+ }
+ else if (dbus_type_is_basic (type))
+ {
+ const void *value;
+ value = va_arg (var_args, const void*);
+
+ if (!dbus_message_iter_append_basic (iter,
+ type,
+ value))
+ _g_dbus_oom ();
+ }
+ else if (type == DBUS_TYPE_ARRAY)
+ {
+ int element_type;
+ DBusMessageIter array;
+ char buf[2];
+
+ element_type = va_arg (var_args, int);
+
+ buf[0] = element_type;
+ buf[1] = '\0';
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ buf,
+ &array))
+ _g_dbus_oom ();
+
+ if (dbus_type_is_fixed (element_type))
+ {
+ const void **value;
+ int n_elements;
+
+ value = va_arg (var_args, const void**);
+ n_elements = va_arg (var_args, int);
+
+ if (!dbus_message_iter_append_fixed_array (&array,
+ element_type,
+ value,
+ n_elements))
+ _g_dbus_oom ();
+ }
+ else if (element_type == DBUS_TYPE_STRING ||
+ element_type == DBUS_TYPE_SIGNATURE ||
+ element_type == DBUS_TYPE_OBJECT_PATH)
+ {
+ const char ***value_p;
+ const char **value;
+ int n_elements;
+ int i;
+
+ value_p = va_arg (var_args, const char***);
+ n_elements = va_arg (var_args, int);
+
+ value = *value_p;
+
+ i = 0;
+ while (i < n_elements)
+ {
+ if (!dbus_message_iter_append_basic (&array,
+ element_type,
+ &value[i]))
+ _g_dbus_oom ();
+ ++i;
+ }
+ }
+ else
+ {
+ g_error ("arrays of %d can't be appended with _g_dbus_message_append_args_valist for now\n",
+ element_type);
+ }
+
+ if (!dbus_message_iter_close_container (iter, &array))
+ _g_dbus_oom ();
+ }
+
+ type = va_arg (var_args, int);
+ }
+}
+
+
+void
+_g_dbus_message_append_args_valist (DBusMessage *message,
+ int first_arg_type,
+ va_list var_args)
+{
+ int type;
+ DBusMessageIter iter;
+
+ g_return_if_fail (message != NULL);
+
+ type = first_arg_type;
+
+ dbus_message_iter_init_append (message, &iter);
+
+ _g_dbus_message_iter_append_args_valist (&iter,
+ first_arg_type,
+ var_args);
+}
+
+dbus_bool_t
+_g_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
+{
+ int spec_type, msg_type, i, dbus_spec_type;
+ dbus_bool_t retval;
+
+
+ retval = FALSE;
+
+ spec_type = first_arg_type;
+ i = 0;
+
+ while (spec_type != DBUS_TYPE_INVALID)
+ {
+ msg_type = dbus_message_iter_get_arg_type (iter);
+
+ if (spec_type == G_DBUS_TYPE_CSTRING)
+ dbus_spec_type = DBUS_TYPE_ARRAY;
+ else
+ dbus_spec_type = spec_type;
+
+ if (msg_type != dbus_spec_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"%c\", but "
+ "is actually of type \"%c\"\n", i,
+ spec_type,
+ msg_type);
+
+ goto out;
+ }
+
+ if (spec_type == G_DBUS_TYPE_CSTRING)
+ {
+ int element_type;
+ char **ptr;
+ const char *str;
+ int n_elements;
+ DBusMessageIter array;
+
+ element_type = dbus_message_iter_get_element_type (iter);
+ if (DBUS_TYPE_BYTE != element_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be an array of \"char\", but "
+ "is actually an array of \"%d\"\n",
+ i,
+ element_type);
+ goto out;
+ }
+
+ ptr = va_arg (var_args, char**);
+ g_assert (ptr != NULL);
+
+ dbus_message_iter_recurse (iter, &array);
+ dbus_message_iter_get_fixed_array (&array,
+ &str, &n_elements);
+ *ptr = g_strndup (str, n_elements);
+ }
+ else if (dbus_type_is_basic (spec_type))
+ {
+ void *ptr;
+
+ ptr = va_arg (var_args, void*);
+
+ g_assert (ptr != NULL);
+
+ dbus_message_iter_get_basic (iter, ptr);
+ }
+ else if (spec_type == DBUS_TYPE_ARRAY)
+ {
+ int element_type;
+ int spec_element_type;
+ const void **ptr;
+ int *n_elements_p;
+ DBusMessageIter array;
+
+ spec_element_type = va_arg (var_args, int);
+ element_type = dbus_message_iter_get_element_type (iter);
+
+ if (spec_element_type != element_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be an array of \"%d\", but "
+ "is actually an array of \"%d\"\n",
+ i,
+ spec_element_type,
+ element_type);
+
+ goto out;
+ }
+
+ if (dbus_type_is_fixed (spec_element_type))
+ {
+ ptr = va_arg (var_args, const void**);
+ n_elements_p = va_arg (var_args, int*);
+
+ g_assert (ptr != NULL);
+ g_assert (n_elements_p != NULL);
+
+ dbus_message_iter_recurse (iter, &array);
+
+ dbus_message_iter_get_fixed_array (&array,
+ ptr, n_elements_p);
+ }
+ else if (spec_element_type == DBUS_TYPE_STRING ||
+ spec_element_type == DBUS_TYPE_SIGNATURE ||
+ spec_element_type == DBUS_TYPE_OBJECT_PATH)
+ {
+ char ***str_array_p;
+ int n_elements;
+ char **str_array;
+
+ str_array_p = va_arg (var_args, char***);
+ n_elements_p = va_arg (var_args, int*);
+
+ g_assert (str_array_p != NULL);
+ g_assert (n_elements_p != NULL);
+
+ /* Count elements in the array */
+ dbus_message_iter_recurse (iter, &array);
+
+ n_elements = 0;
+ while (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_INVALID)
+ {
+ ++n_elements;
+ dbus_message_iter_next (&array);
+ }
+
+ str_array = g_new0 (char*, n_elements + 1);
+ if (str_array == NULL)
+ {
+ _g_dbus_oom ();
+ goto out;
+ }
+
+ /* Now go through and dup each string */
+ dbus_message_iter_recurse (iter, &array);
+
+ i = 0;
+ while (i < n_elements)
+ {
+ const char *s;
+ dbus_message_iter_get_basic (&array, &s);
+
+ str_array[i] = g_strdup (s);
+ if (str_array[i] == NULL)
+ {
+ g_strfreev (str_array);
+ _g_dbus_oom ();
+ goto out;
+ }
+
+ ++i;
+
+ if (!dbus_message_iter_next (&array))
+ g_assert (i == n_elements);
+ }
+
+ g_assert (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_INVALID);
+ g_assert (i == n_elements);
+ g_assert (str_array[i] == NULL);
+
+ *str_array_p = str_array;
+ *n_elements_p = n_elements;
+ }
+ }
+
+ spec_type = va_arg (var_args, int);
+ if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Message has only %d arguments, but more were expected", i);
+ goto out;
+ }
+
+ i++;
+ }
+
+ retval = TRUE;
+
+ out:
+ return retval;
+}
+
+dbus_bool_t
+_g_dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+ dbus_bool_t res;
+
+ va_start (var_args, first_arg_type);
+ res = _g_dbus_message_iter_get_args_valist (iter, error,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+ return res;
+}
+
+/* Same as the dbus one, except doesn't give OOM and handles
+ G_DBUS_TYPE_CSTRING
+*/
+void
+_g_dbus_message_append_args (DBusMessage *message,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (message != NULL);
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (message,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+}
+
+void
+_g_dbus_message_iter_append_args (DBusMessageIter *iter,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (iter != NULL);
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_iter_append_args_valist (iter,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+}
+
+void
+_g_error_from_dbus (DBusError *derror,
+ GError **error)
+{
+ const char *name, *end;
+ GString *str;
+ GQuark domain;
+ int code;
+
+ if (g_str_has_prefix (derror->name, "org.glib.GError."))
+ {
+ domain = 0;
+ code = 0;
+
+ name = derror->name + strlen ("org.glib.GError.");
+ end = strchr (name, '.');
+ if (end)
+ {
+ str = g_string_new (NULL);
+ append_unescaped_dbus_name (str, name, end);
+ domain = g_quark_from_string (str->str);
+ g_string_free (str, TRUE);
+
+ end++; /* skip . */
+ if (*end++ == 'c')
+ code = atoi (end);
+ }
+
+ g_set_error_literal (error, domain, code, derror->message);
+ }
+ /* TODO: Special case other types, like DBUS_ERROR_NO_MEMORY etc? */
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "DBus error %s: %s", derror->name, derror->message);
+}
+
+GList *
+_g_dbus_bus_list_names_with_prefix (DBusConnection *connection,
+ const char *prefix,
+ DBusError *error)
+{
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, array;
+ GList *names;
+
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "ListNames");
+ if (message == NULL)
+ return NULL;
+
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ return NULL;
+
+ names = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
+ (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
+ goto out;
+
+ for (dbus_message_iter_recurse (&iter, &array);
+ dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_STRING;
+ dbus_message_iter_next (&array))
+ {
+ char *name;
+ dbus_message_iter_get_basic (&array, &name);
+ if (g_str_has_prefix (name, prefix))
+ names = g_list_prepend (names, g_strdup (name));
+ }
+
+ names = g_list_reverse (names);
+
+ out:
+ dbus_message_unref (reply);
+ return names;
+}
+
+/*************************************************************************
+ * Helper fd source *
+ ************************************************************************/
+
+typedef struct
+{
+ GSource source;
+ GPollFD pollfd;
+ GCancellable *cancellable;
+ gulong cancelled_tag;
+} FDSource;
+
+static gboolean
+fd_source_prepare (GSource *source,
+ gint *timeout)
+{
+ FDSource *fd_source = (FDSource *)source;
+ *timeout = -1;
+
+ return g_cancellable_is_cancelled (fd_source->cancellable);
+}
+
+static gboolean
+fd_source_check (GSource *source)
+{
+ FDSource *fd_source = (FDSource *)source;
+
+ return
+ g_cancellable_is_cancelled (fd_source->cancellable) ||
+ fd_source->pollfd.revents != 0;
+}
+
+static gboolean
+fd_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+
+{
+ GFDSourceFunc func = (GFDSourceFunc)callback;
+ FDSource *fd_source = (FDSource *)source;
+
+ g_assert (func != NULL);
+
+ return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
+}
+
+static void
+fd_source_finalize (GSource *source)
+{
+ FDSource *fd_source = (FDSource *)source;
+
+ if (fd_source->cancelled_tag)
+ g_signal_handler_disconnect (fd_source->cancellable,
+ fd_source->cancelled_tag);
+
+ if (fd_source->cancellable)
+ g_object_unref (fd_source->cancellable);
+}
+
+static GSourceFuncs fd_source_funcs = {
+ fd_source_prepare,
+ fd_source_check,
+ fd_source_dispatch,
+ fd_source_finalize
+};
+
+/* Might be called on another thread */
+static void
+fd_source_cancelled_cb (GCancellable *cancellable,
+ gpointer data)
+{
+ /* Wake up the mainloop in case we're waiting on async calls with FDSource */
+ g_main_context_wakeup (NULL);
+}
+
+/* Two __ to avoid conflict with gio version */
+GSource *
+__g_fd_source_new (int fd,
+ gushort events,
+ GCancellable *cancellable)
+{
+ GSource *source;
+ FDSource *fd_source;
+
+ source = g_source_new (&fd_source_funcs, sizeof (FDSource));
+ fd_source = (FDSource *)source;
+
+ if (cancellable)
+ fd_source->cancellable = g_object_ref (cancellable);
+
+ fd_source->pollfd.fd = fd;
+ fd_source->pollfd.events = events;
+ g_source_add_poll (source, &fd_source->pollfd);
+
+ if (cancellable)
+ fd_source->cancelled_tag =
+ g_signal_connect_data (cancellable, "cancelled",
+ (GCallback)fd_source_cancelled_cb,
+ NULL, NULL,
+ 0);
+
+ return source;
+}
+
+
+/*************************************************************************
+ * *
+ * dbus mainloop integration for async ops *
+ * *
+ *************************************************************************/
+
+static gint32 main_integration_data_slot = -1;
+static GOnce once_init_main_integration = G_ONCE_INIT;
+
+/**
+ * A GSource subclass for dispatching DBusConnection messages.
+ * We need this on top of the IO handlers, because sometimes
+ * there are messages to dispatch queued up but no IO pending.
+ *
+ * The source is owned by the connection (and the main context
+ * while that is alive)
+ */
+typedef struct
+{
+ GSource source;
+
+ DBusConnection *connection;
+ GSList *ios;
+ GSList *timeouts;
+} DBusSource;
+
+typedef struct
+{
+ DBusSource *dbus_source;
+ GSource *source;
+ DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+ DBusSource *dbus_source;
+ GSource *source;
+ DBusTimeout *timeout;
+} TimeoutHandler;
+
+static gpointer
+main_integration_init (gpointer arg)
+{
+ if (!dbus_connection_allocate_data_slot (&main_integration_data_slot))
+ g_error ("Unable to allocate data slot");
+
+ return NULL;
+}
+
+static gboolean
+dbus_source_prepare (GSource *source,
+ gint *timeout)
+{
+ DBusConnection *connection = ((DBusSource *)source)->connection;
+
+ *timeout = -1;
+
+ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+dbus_source_check (GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean
+dbus_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ DBusConnection *connection = ((DBusSource *)source)->connection;
+
+ dbus_connection_ref (connection);
+
+ /* Only dispatch once - we don't want to starve other GSource */
+ dbus_connection_dispatch (connection);
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static gboolean
+io_handler_dispatch (gpointer data,
+ GIOCondition condition,
+ int fd)
+{
+ IOHandler *handler = data;
+ guint dbus_condition = 0;
+ DBusConnection *connection;
+
+ connection = handler->dbus_source->connection;
+
+ if (connection)
+ dbus_connection_ref (connection);
+
+ if (condition & G_IO_IN)
+ dbus_condition |= DBUS_WATCH_READABLE;
+ if (condition & G_IO_OUT)
+ dbus_condition |= DBUS_WATCH_WRITABLE;
+ if (condition & G_IO_ERR)
+ dbus_condition |= DBUS_WATCH_ERROR;
+ if (condition & G_IO_HUP)
+ dbus_condition |= DBUS_WATCH_HANGUP;
+
+ /* Note that we don't touch the handler after this, because
+ * dbus may have disabled the watch and thus killed the
+ * handler.
+ */
+ dbus_watch_handle (handler->watch, dbus_condition);
+ handler = NULL;
+
+ if (connection)
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static void
+io_handler_free (IOHandler *handler)
+{
+ DBusSource *dbus_source;
+
+ dbus_source = handler->dbus_source;
+ dbus_source->ios = g_slist_remove (dbus_source->ios, handler);
+
+ g_source_destroy (handler->source);
+ g_source_unref (handler->source);
+ g_free (handler);
+}
+
+static void
+dbus_source_add_watch (DBusSource *dbus_source,
+ DBusWatch *watch)
+{
+ guint flags;
+ GIOCondition condition;
+ IOHandler *handler;
+ int fd;
+
+ if (!dbus_watch_get_enabled (watch))
+ return;
+
+ g_assert (dbus_watch_get_data (watch) == NULL);
+
+ flags = dbus_watch_get_flags (watch);
+
+ condition = G_IO_ERR | G_IO_HUP;
+ if (flags & DBUS_WATCH_READABLE)
+ condition |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ condition |= G_IO_OUT;
+
+ handler = g_new0 (IOHandler, 1);
+ handler->dbus_source = dbus_source;
+ handler->watch = watch;
+
+#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
+ fd = dbus_watch_get_unix_fd (watch);
+#else
+ fd = dbus_watch_get_fd (watch);
+#endif
+
+ handler->source = __g_fd_source_new (fd, condition, NULL);
+ g_source_set_callback (handler->source,
+ (GSourceFunc) io_handler_dispatch, handler,
+ NULL);
+ g_source_attach (handler->source, NULL);
+
+ dbus_source->ios = g_slist_prepend (dbus_source->ios, handler);
+ dbus_watch_set_data (watch, handler,
+ (DBusFreeFunction)io_handler_free);
+}
+
+static void
+dbus_source_remove_watch (DBusSource *dbus_source,
+ DBusWatch *watch)
+{
+ dbus_watch_set_data (watch, NULL, NULL);
+}
+
+static void
+timeout_handler_free (TimeoutHandler *handler)
+{
+ DBusSource *dbus_source;
+
+ dbus_source = handler->dbus_source;
+ dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler);
+
+ g_source_destroy (handler->source);
+ g_source_unref (handler->source);
+ g_free (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer data)
+{
+ TimeoutHandler *handler = data;
+
+ dbus_timeout_handle (handler->timeout);
+
+ return TRUE;
+}
+
+static void
+dbus_source_add_timeout (DBusSource *dbus_source,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return;
+
+ g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+ handler = g_new0 (TimeoutHandler, 1);
+ handler->dbus_source = dbus_source;
+ handler->timeout = timeout;
+
+ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+ g_source_set_callback (handler->source,
+ timeout_handler_dispatch, handler,
+ NULL);
+ g_source_attach (handler->source, NULL);
+
+ /* handler->source is owned by the context here */
+ dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler);
+
+ dbus_timeout_set_data (timeout, handler,
+ (DBusFreeFunction)timeout_handler_free);
+}
+
+static void
+dbus_source_remove_timeout (DBusSource *source,
+ DBusTimeout *timeout)
+{
+ dbus_timeout_set_data (timeout, NULL, NULL);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+ gpointer data)
+{
+ DBusSource *dbus_source = data;
+
+ dbus_source_add_watch (dbus_source, watch);
+
+ return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+ gpointer data)
+{
+ DBusSource *dbus_source = data;
+
+ dbus_source_remove_watch (dbus_source, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove */
+ if (dbus_watch_get_enabled (watch))
+ add_watch (watch, data);
+ else
+ remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ DBusSource *source = data;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return TRUE;
+
+ dbus_source_add_timeout (source, timeout);
+
+ return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ DBusSource *source = data;
+
+ dbus_source_remove_timeout (source, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_timeout_get_enabled (timeout))
+ add_timeout (timeout, data);
+ else
+ remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+ g_main_context_wakeup (NULL);
+}
+
+static const GSourceFuncs dbus_source_funcs = {
+ dbus_source_prepare,
+ dbus_source_check,
+ dbus_source_dispatch
+};
+
+/* Called when the connection dies or when we're unintegrating from mainloop */
+static void
+dbus_source_free (DBusSource *dbus_source)
+{
+ while (dbus_source->ios)
+ {
+ IOHandler *handler = dbus_source->ios->data;
+
+ dbus_watch_set_data (handler->watch, NULL, NULL);
+ }
+
+ while (dbus_source->timeouts)
+ {
+ TimeoutHandler *handler = dbus_source->timeouts->data;
+
+ dbus_timeout_set_data (handler->timeout, NULL, NULL);
+ }
+
+ /* Remove from mainloop */
+ g_source_destroy ((GSource *)dbus_source);
+
+ g_source_unref ((GSource *)dbus_source);
+}
+
+void
+_g_dbus_connection_integrate_with_main (DBusConnection *connection)
+{
+ DBusSource *dbus_source;
+
+ g_once (&once_init_main_integration, main_integration_init, NULL);
+
+ g_assert (connection != NULL);
+
+ _g_dbus_connection_remove_from_main (connection);
+
+ dbus_source = (DBusSource *)
+ g_source_new ((GSourceFuncs*)&dbus_source_funcs,
+ sizeof (DBusSource));
+
+ dbus_source->connection = connection;
+
+ if (!dbus_connection_set_watch_functions (connection,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ dbus_source, NULL))
+ _g_dbus_oom ();
+
+ if (!dbus_connection_set_timeout_functions (connection,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ dbus_source, NULL))
+ _g_dbus_oom ();
+
+ dbus_connection_set_wakeup_main_function (connection,
+ wakeup_main,
+ dbus_source, NULL);
+
+ /* Owned by both connection and mainloop (until destroy) */
+ g_source_attach ((GSource *)dbus_source, NULL);
+
+ if (!dbus_connection_set_data (connection,
+ main_integration_data_slot,
+ dbus_source, (DBusFreeFunction)dbus_source_free))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_connection_remove_from_main (DBusConnection *connection)
+{
+ g_once (&once_init_main_integration, main_integration_init, NULL);
+
+ if (!dbus_connection_set_data (connection,
+ main_integration_data_slot,
+ NULL, NULL))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_message_iter_copy (DBusMessageIter *dest,
+ DBusMessageIter *source)
+{
+ int type, element_type;
+
+ while (dbus_message_iter_get_arg_type (source) != DBUS_TYPE_INVALID)
+ {
+ type = dbus_message_iter_get_arg_type (source);
+
+ if (dbus_type_is_basic (type))
+ {
+ dbus_uint64_t value;
+ dbus_message_iter_get_basic (source, &value);
+ dbus_message_iter_append_basic (dest, type, &value);
+ }
+ else if (type == DBUS_TYPE_ARRAY)
+ {
+ DBusMessageIter source_array, dest_array;
+ void *value;
+ int n_elements;
+ char buf[2];
+
+ element_type = dbus_message_iter_get_element_type (source);
+ if (dbus_type_is_fixed (element_type))
+ {
+ buf[0] = element_type;
+ buf[1] = '\0';
+
+ dbus_message_iter_recurse (source, &source_array);
+ dbus_message_iter_get_fixed_array (&source_array, &value, &n_elements);
+
+ if (!dbus_message_iter_open_container (dest, DBUS_TYPE_ARRAY,
+ buf, &dest_array))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_fixed_array (&dest_array,
+ element_type,
+ &value, n_elements))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (dest, &dest_array))
+ _g_dbus_oom ();
+ }
+ else
+ g_error ("Unsupported array type %c in _g_dbus_message_iter_copy", element_type);
+ }
+ else
+ g_error ("Unsupported type %c in _g_dbus_message_iter_copy", type);
+
+ dbus_message_iter_next (source);
+ }
+
+}
+
+typedef struct {
+ GAsyncDBusCallback callback;
+ gpointer user_data;
+ GError *io_error;
+
+
+ /* protected by async_call lock: */
+ gboolean ran; /* the pending_call reply handler ran */
+ gboolean idle; /* we queued an idle */
+
+ /* only used for idle */
+ DBusPendingCall *pending;
+} AsyncDBusCallData;
+
+/* Lock to protect the data for working around racecondition
+ between send_with_reply and pending_set_notify */
+G_LOCK_DEFINE_STATIC(async_call);
+
+static void
+handle_async_reply (DBusPendingCall *pending,
+ AsyncDBusCallData *data)
+{
+ DBusMessage *reply;
+ GError *error;
+
+ reply = dbus_pending_call_steal_reply (pending);
+
+ error = NULL;
+ if (_g_error_from_message (reply, &error))
+ {
+ if (data->callback)
+ data->callback (NULL, error, data->user_data);
+ g_error_free (error);
+ }
+ else
+ {
+ if (data->callback)
+ data->callback (reply, NULL, data->user_data);
+ }
+
+ dbus_message_unref (reply);
+}
+
+static void
+async_call_reply (DBusPendingCall *pending,
+ void *_data)
+{
+ AsyncDBusCallData *data = _data;
+
+ G_LOCK (async_call);
+ if (data->idle)
+ return;
+ data->ran = TRUE;
+ G_UNLOCK (async_call);
+
+ handle_async_reply (pending, data);
+}
+
+static gboolean
+idle_async_callback (void *_data)
+{
+ AsyncDBusCallData *data = _data;
+ handle_async_reply (data->pending, data);
+ dbus_pending_call_unref (data->pending);
+ return FALSE;
+}
+
+static gboolean
+async_call_error_at_idle (gpointer _data)
+{
+ AsyncDBusCallData *data = _data;
+
+ if (data->callback)
+ data->callback (NULL, data->io_error, data->user_data);
+
+ g_error_free (data->io_error);
+ g_free (data);
+
+ return FALSE;
+}
+
+void
+_g_dbus_connection_call_async (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_msecs,
+ GAsyncDBusCallback callback,
+ gpointer user_data)
+{
+ AsyncDBusCallData *data;
+ DBusPendingCall *pending_call;
+ DBusError derror;
+
+ data = g_new0 (AsyncDBusCallData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (connection == NULL)
+ {
+ dbus_error_init (&derror);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ if (connection == NULL)
+ {
+ g_set_error_literal (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Can't open dbus connection");
+ g_idle_add (async_call_error_at_idle, data);
+ dbus_error_free (&derror);
+ return;
+ }
+ }
+
+ if (!dbus_connection_send_with_reply (connection, message, &pending_call, timeout_msecs))
+ _g_dbus_oom ();
+
+ if (pending_call == NULL)
+ {
+ g_set_error (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ "Connection is closed");
+ g_idle_add (async_call_error_at_idle, data);
+ return;
+ }
+
+ if (!dbus_pending_call_set_notify (pending_call,
+ async_call_reply,
+ data, g_free))
+ _g_dbus_oom ();
+
+
+ /* All this is required to work around a race condition between
+ * send_with_reply and pending_call_set_notify :/
+ */
+ G_LOCK (async_call);
+
+ if (dbus_pending_call_get_completed (pending_call) &&
+ !data->ran)
+ {
+ data->idle = TRUE;
+ data->pending = dbus_pending_call_ref (pending_call);
+ g_idle_add (idle_async_callback, data);
+ }
+
+ G_UNLOCK (async_call);
+
+
+ dbus_pending_call_unref (pending_call);
+}
diff --git a/trunk/common/gdbusutils.h b/trunk/common/gdbusutils.h
new file mode 100644
index 00000000..1a94330b
--- /dev/null
+++ b/trunk/common/gdbusutils.h
@@ -0,0 +1,95 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DBUS_UTILS_H__
+#define __G_DBUS_UTILS_H__
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef gboolean (*GFDSourceFunc) (gpointer data,
+ GIOCondition condition,
+ int fd);
+typedef void (*GAsyncDBusCallback) (DBusMessage *reply,
+ GError *error,
+ gpointer user_data);
+
+/* Only used internally, never on wire */
+#define G_DBUS_TYPE_CSTRING 1024
+
+GList * _g_dbus_bus_list_names_with_prefix (DBusConnection *connection,
+ const char *prefix,
+ DBusError *error);
+void _g_dbus_message_iter_append_cstring (DBusMessageIter *iter,
+ const char *str);
+void _g_dbus_message_iter_append_args_valist (DBusMessageIter *iter,
+ int first_arg_type,
+ va_list var_args);
+void _g_dbus_message_iter_append_args (DBusMessageIter *iter,
+ int first_arg_type,
+ ...);
+void _g_dbus_message_append_args_valist (DBusMessage *message,
+ int first_arg_type,
+ va_list var_args);
+void _g_dbus_message_append_args (DBusMessage *message,
+ int first_arg_type,
+ ...);
+dbus_bool_t _g_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args);
+dbus_bool_t _g_dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...);
+void _g_error_from_dbus (DBusError *derror,
+ GError **error);
+gboolean _g_error_from_message (DBusMessage *message,
+ GError **error);
+DBusMessage *_dbus_message_new_from_gerror (DBusMessage *message,
+ GError *error);
+DBusMessage *_dbus_message_new_gerror (DBusMessage *message,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...);
+void _g_dbus_connection_integrate_with_main (DBusConnection *connection);
+void _g_dbus_connection_remove_from_main (DBusConnection *connection);
+GSource * __g_fd_source_new (int fd,
+ gushort events,
+ GCancellable *cancellable);
+void _g_dbus_message_iter_copy (DBusMessageIter *dest,
+ DBusMessageIter *source);
+void _g_dbus_oom (void) G_GNUC_NORETURN;
+void _g_dbus_connection_call_async (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_msecs,
+ GAsyncDBusCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+
+#endif /* __G_DBUS_UTILS_H__ */
diff --git a/trunk/common/gmountoperationdbus.c b/trunk/common/gmountoperationdbus.c
new file mode 100644
index 00000000..1027b3a9
--- /dev/null
+++ b/trunk/common/gmountoperationdbus.c
@@ -0,0 +1,324 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <dbus/dbus.h>
+
+#define I_(string) g_intern_static_string (string)
+
+#include <gio/gio.h>
+#include "gmountoperationdbus.h"
+#include "gvfsdaemonprotocol.h"
+#include "gdbusutils.h"
+#include <glib/gi18n-lib.h>
+
+typedef struct
+{
+ GMountOperation *op;
+ char *obj_path;
+ char *dbus_id;
+ DBusConnection *connection;
+} GMountOperationDBus;
+
+static DBusHandlerResult mount_op_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+static void mount_op_unregister_function (DBusConnection *connection,
+ void *user_data);
+static void mount_op_ask_password (GMountOperationDBus *op_dbus,
+ DBusMessage *message);
+static void mount_op_ask_question (GMountOperationDBus *op_dbus,
+ DBusMessage *message);
+
+static void
+g_mount_operation_dbus_free (GMountOperationDBus *op_dbus)
+{
+ if (op_dbus->connection)
+ {
+ dbus_connection_unregister_object_path (op_dbus->connection,
+ op_dbus->obj_path);
+ dbus_connection_unref (op_dbus->connection);
+ }
+ g_free (op_dbus->dbus_id);
+ g_free (op_dbus->obj_path);
+ g_free (op_dbus);
+}
+
+GMountSource *
+g_mount_operation_dbus_wrap (GMountOperation *op,
+ DBusConnection *connection)
+{
+ GMountOperationDBus *op_dbus;
+ static int mount_id = 0;
+ DBusObjectPathVTable mount_vtable = {
+ mount_op_unregister_function,
+ mount_op_message_function
+ };
+
+ if (op == NULL)
+ return g_mount_source_new_dummy ();
+
+ op_dbus = g_new0 (GMountOperationDBus, 1);
+
+ op_dbus->op = op;
+ op_dbus->connection = dbus_connection_ref (connection);
+ op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++);
+ if (op_dbus->connection)
+ {
+ op_dbus->dbus_id = g_strdup (dbus_bus_get_unique_name (op_dbus->connection));
+ if (!dbus_connection_register_object_path (op_dbus->connection,
+ op_dbus->obj_path,
+ &mount_vtable,
+ op_dbus))
+ _g_dbus_oom ();
+ }
+
+ g_object_set_data_full (G_OBJECT (op), "dbus-op",
+ op_dbus, (GDestroyNotify)g_mount_operation_dbus_free);
+
+ return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path);
+}
+
+/**
+ * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed).
+ * Found in #DBusObjectPathVTable.
+ */
+static void
+mount_op_unregister_function (DBusConnection *connection,
+ void *user_data)
+{
+}
+
+/**
+ * Called when a message is sent to a registered object path. Found in
+ * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path()
+ * or dbus_connection_register_fallback().
+ */
+static DBusHandlerResult
+mount_op_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GMountOperationDBus *op_dbus = user_data;
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD))
+ mount_op_ask_password (op_dbus, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION))
+ mount_op_ask_question (op_dbus, message);
+ else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+mount_op_send_reply (GMountOperationDBus *op_dbus,
+ DBusMessage *reply)
+{
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+
+ g_signal_handlers_disconnect_matched (op_dbus->op,
+ G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA,
+ g_signal_lookup ("reply", G_TYPE_MOUNT_OPERATION),
+ 0,
+ NULL,
+ NULL,
+ reply);
+ dbus_message_unref (reply);
+}
+
+static void
+ask_password_reply (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer data)
+{
+ DBusMessage *reply = data;
+ const char *username, *password, *domain;
+ dbus_bool_t anonymous;
+ guint32 password_save;
+ dbus_bool_t handled, abort_dbus;
+ GMountOperationDBus *op_dbus;
+
+ op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
+
+ handled = (result != G_MOUNT_OPERATION_UNHANDLED);
+ abort_dbus = (result == G_MOUNT_OPERATION_ABORTED);
+
+ password = g_mount_operation_get_password (op);
+ if (password == NULL)
+ password = "";
+ username = g_mount_operation_get_username (op);
+ if (username == NULL)
+ username = "";
+ domain = g_mount_operation_get_domain (op);
+ if (domain == NULL)
+ domain = "";
+ anonymous = g_mount_operation_get_anonymous (op);
+ password_save = g_mount_operation_get_password_save (op);
+
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &abort_dbus,
+ DBUS_TYPE_STRING, &password,
+ DBUS_TYPE_STRING, &username,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_BOOLEAN, &anonymous,
+ DBUS_TYPE_UINT32, &password_save,
+ 0);
+
+ mount_op_send_reply (op_dbus, reply);
+}
+
+static void
+mount_op_ask_password (GMountOperationDBus *op_dbus,
+ DBusMessage *message)
+{
+ const char *message_string, *default_user, *default_domain;
+ guint32 flags;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError error;
+
+ reply = NULL;
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&error);
+ if (!_g_dbus_message_iter_get_args (&iter,
+ &error,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_STRING, &default_user,
+ DBUS_TYPE_STRING, &default_domain,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ reply = dbus_message_new_error (message, error.name, error.message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+ dbus_message_unref (reply);
+ dbus_error_free (&error);
+ return;
+ }
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ g_signal_connect (op_dbus->op, "reply", (GCallback)ask_password_reply, reply);
+
+ g_signal_emit_by_name (op_dbus->op, "ask_password",
+ message_string,
+ default_user,
+ default_domain,
+ flags);
+}
+
+static void
+ask_question_reply (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer data)
+{
+ DBusMessage *reply = data;
+ guint32 choice;
+ dbus_bool_t handled, abort_dbus;
+ GMountOperationDBus *op_dbus;
+
+ op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
+
+ handled = (result != G_MOUNT_OPERATION_UNHANDLED);
+ abort_dbus = (result == G_MOUNT_OPERATION_ABORTED);
+
+ choice = g_mount_operation_get_choice (op);
+
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &abort_dbus,
+ DBUS_TYPE_UINT32, &choice,
+ 0);
+
+ mount_op_send_reply (op_dbus, reply);
+}
+
+static void
+mount_op_ask_question (GMountOperationDBus *op_dbus,
+ DBusMessage *message)
+{
+ const char *message_string;
+ char **choices;
+ int num_choices;
+ dbus_bool_t handled = FALSE;
+ DBusMessage *reply;
+ DBusError error;
+ gboolean res;
+ DBusMessageIter iter;
+
+ reply = NULL;
+
+ dbus_message_iter_init (message, &iter);
+ dbus_error_init (&error);
+ if (!_g_dbus_message_iter_get_args (&iter,
+ &error,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &choices, &num_choices,
+ 0))
+ {
+ reply = dbus_message_new_error (message, error.name, error.message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+ dbus_message_unref (reply);
+ dbus_error_free (&error);
+ return;
+ }
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ g_signal_connect (op_dbus->op, "reply", (GCallback)ask_question_reply, reply);
+
+ g_signal_emit_by_name (op_dbus->op, "ask_question",
+ message_string,
+ choices,
+ &res);
+ if (!res)
+ {
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ 0);
+ mount_op_send_reply (op_dbus, reply);
+ }
+
+ dbus_free_string_array (choices);
+}
diff --git a/trunk/common/gmountoperationdbus.h b/trunk/common/gmountoperationdbus.h
new file mode 100644
index 00000000..26ee4013
--- /dev/null
+++ b/trunk/common/gmountoperationdbus.h
@@ -0,0 +1,40 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_OPERATION_DBUS_H__
+#define __G_MOUNT_OPERATION_DBUS_H__
+
+#include <sys/stat.h>
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gmountspec.h>
+#include <gmountsource.h>
+
+G_BEGIN_DECLS
+
+GMountSource *g_mount_operation_dbus_wrap (GMountOperation *op,
+ DBusConnection *connection);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_OPERATION_DBUS_H__ */
diff --git a/trunk/common/gmountsource.c b/trunk/common/gmountsource.c
new file mode 100644
index 00000000..e801d647
--- /dev/null
+++ b/trunk/common/gmountsource.c
@@ -0,0 +1,716 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <gmountsource.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+#include <gvfsdaemonprotocol.h>
+
+struct _GMountSource
+{
+ GObject parent_instance;
+
+ char *dbus_id;
+ char *obj_path;
+};
+
+G_DEFINE_TYPE (GMountSource, g_mount_source, G_TYPE_OBJECT)
+
+static void
+g_mount_source_finalize (GObject *object)
+{
+ GMountSource *source;
+
+ source = G_MOUNT_SOURCE (object);
+
+ g_free (source->dbus_id);
+ g_free (source->obj_path);
+
+ if (G_OBJECT_CLASS (g_mount_source_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_mount_source_parent_class)->finalize) (object);
+}
+
+static void
+g_mount_source_class_init (GMountSourceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mount_source_finalize;
+}
+
+static void
+g_mount_source_init (GMountSource *mount_source)
+{
+}
+
+GMountSource *
+g_mount_source_new (const char *dbus_id,
+ const char *obj_path)
+{
+ GMountSource *source;
+
+ source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
+
+ source->dbus_id = g_strdup (dbus_id);
+ source->obj_path = g_strdup (obj_path);
+
+ return source;
+}
+
+GMountSource *
+g_mount_source_new_dummy (void)
+{
+ GMountSource *source;
+
+ source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
+
+ source->dbus_id = g_strdup ("");
+ source->obj_path = g_strdup ("/");
+
+ return source;
+}
+
+
+void
+g_mount_source_to_dbus (GMountSource *source,
+ DBusMessage *message)
+{
+ g_assert (source->dbus_id != NULL);
+ g_assert (source->obj_path != NULL);
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &source->dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &source->obj_path,
+ 0))
+ _g_dbus_oom ();
+
+}
+
+const char *
+g_mount_source_get_dbus_id (GMountSource *mount_source)
+{
+ return mount_source->dbus_id;
+}
+
+const char *
+g_mount_source_get_obj_path (GMountSource *mount_source)
+{
+ return mount_source->obj_path;
+}
+
+typedef struct AskPasswordData AskPasswordData;
+
+struct AskPasswordData {
+
+ /* results: */
+ gboolean aborted;
+ char *password;
+ char *username;
+ char *domain;
+ GPasswordSave password_save;
+ gboolean anonymous;
+};
+
+typedef struct AskSyncData AskSyncData;
+
+struct AskSyncData {
+
+ /* For sync calls */
+ GMutex *mutex;
+ GCond *cond;
+
+ /* results: */
+ GAsyncResult *result;
+};
+
+static void
+ask_password_data_free (gpointer _data)
+{
+ AskPasswordData *data = (AskPasswordData *) _data;
+ g_free (data->password);
+ g_free (data->username);
+ g_free (data->domain);
+ g_free (data);
+}
+
+/* the callback from dbus -> main thread */
+static void
+ask_password_reply (DBusMessage *reply,
+ GError *error,
+ gpointer _data)
+{
+ GSimpleAsyncResult *result;
+ AskPasswordData *data;
+ dbus_bool_t handled, aborted, anonymous;
+ guint32 password_save;
+ const char *password, *username, *domain;
+ DBusMessageIter iter;
+
+ result = G_SIMPLE_ASYNC_RESULT (_data);
+ handled = TRUE;
+
+ data = g_new0 (AskPasswordData, 1);
+ g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free);
+
+ if (reply == NULL)
+ {
+ data->aborted = TRUE;
+ }
+ else
+ {
+ dbus_message_iter_init (reply, &iter);
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &aborted,
+ DBUS_TYPE_STRING, &password,
+ DBUS_TYPE_STRING, &username,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_BOOLEAN, &anonymous,
+ DBUS_TYPE_UINT32, &password_save,
+ 0))
+ data->aborted = TRUE;
+ else
+ {
+ data->aborted = aborted;
+
+ if (!anonymous)
+ {
+ data->password = g_strdup (password);
+ data->username = *username == 0 ? NULL : g_strdup (username);
+ data->domain = *domain == 0 ? NULL : g_strdup (domain);
+ }
+ data->password_save = (GPasswordSave)password_save;
+ data->anonymous = anonymous;
+
+ /* TODO: handle more args */
+ }
+ }
+
+ if (handled == FALSE)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
+ }
+
+ g_simple_async_result_complete (result);
+}
+
+void
+g_mount_source_ask_password_async (GMountSource *source,
+ const char *message_string,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ DBusMessage *message;
+ guint32 flags_as_int;
+
+
+ /* If no dbus id specified, reply that we weren't handled */
+ if (source->dbus_id[0] == 0)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (source),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal Error");
+ return;
+ }
+
+ if (message_string == NULL)
+ message_string = "";
+ if (default_user == NULL)
+ default_user = "";
+ if (default_domain == NULL)
+ default_domain = "";
+
+ flags_as_int = flags;
+
+ message = dbus_message_new_method_call (source->dbus_id,
+ source->obj_path,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD);
+
+ _g_dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_STRING, &default_user,
+ DBUS_TYPE_STRING, &default_domain,
+ DBUS_TYPE_UINT32, &flags_as_int,
+ 0);
+
+ result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+ g_mount_source_ask_password_async);
+ /* 30 minute timeout */
+ _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
+ ask_password_reply, result);
+ dbus_message_unref (message);
+
+}
+
+/**
+ * g_mount_source_ask_password_finish:
+ * @source: the source to query
+ * @result: the async result
+ * @aborted: set to %TRUE if the password dialog was aborted by the user
+ * @password_out: the to the password set by the user or to %NULL if none
+ * @user_out: set to the username set by the user or to %NULL if none
+ * @domain_out: set to the domain set by the user or to %NULL if none
+ * @anonymous_out: set to %TRUE if the user selected anonymous login. This
+ * should only happen if G_ASK_PASSWORD_ANONYMOUS_SUPPORTED
+ * was supplied whe querying the password.
+ * @password_save_out: set to the save flags to use when saving the password
+ * in the keyring.
+ *
+ * Requests the reply parameters from a g_mount_source_ask_password_async()
+ * request. All out parameters can be set to %NULL to ignore them.
+ * <note><para>Please be aware that out parameters other than the password
+ * are set to %NULL if the user don't specify them so make sure to
+ * check them.</para></note>
+ *
+ * Returns: %FALSE if the async reply contained an error.
+ **/
+gboolean
+g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out)
+{
+ AskPasswordData *data, def = { TRUE, };
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, NULL))
+ data = &def;
+ else
+ data = (AskPasswordData *) g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (aborted)
+ *aborted = data->aborted;
+
+ if (password_out)
+ {
+ *password_out = data->password;
+ data->password = NULL;
+ }
+
+ if (user_out)
+ {
+ *user_out = data->username;
+ data->username = NULL;
+ }
+
+ if (domain_out)
+ {
+ *domain_out = data->domain;
+ data->domain = NULL;
+ }
+
+ if (anonymous_out)
+ *anonymous_out = data->anonymous;
+
+ if (password_save_out)
+ *password_save_out = data->password_save;
+
+ return data != &def;
+}
+
+
+static void
+ask_reply_sync (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AskSyncData *data;
+
+ data = (AskSyncData *) user_data;
+
+ data->result = g_object_ref (res);
+
+ /* Wake up sync call thread */
+ g_mutex_lock (data->mutex);
+ g_cond_signal (data->cond);
+ g_mutex_unlock (data->mutex);
+}
+
+gboolean
+g_mount_source_ask_password (GMountSource *source,
+ const char *message_string,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ gboolean *aborted_out,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out)
+{
+ gboolean handled;
+ AskSyncData data = {NULL};
+
+ data.mutex = g_mutex_new ();
+ data.cond = g_cond_new ();
+
+ g_mutex_lock (data.mutex);
+
+
+ g_mount_source_ask_password_async (source,
+ message_string,
+ default_user,
+ default_domain,
+ flags,
+ ask_reply_sync,
+ &data);
+
+ g_cond_wait(data.cond, data.mutex);
+ g_mutex_unlock (data.mutex);
+
+ g_cond_free (data.cond);
+ g_mutex_free (data.mutex);
+
+
+ handled = g_mount_source_ask_password_finish (source,
+ data.result,
+ aborted_out,
+ password_out,
+ user_out,
+ domain_out,
+ anonymous_out,
+ password_save_out);
+ g_object_unref (data.result);
+
+ return handled;
+}
+
+static void
+op_ask_password_reply (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GMountOperationResult result;
+ GMountOperation *op;
+ GMountSource *source;
+ gboolean handled, aborted;
+ char *username;
+ char *password;
+ char *domain;
+ GPasswordSave password_save;
+
+ source = G_MOUNT_SOURCE (source_object);
+ op = G_MOUNT_OPERATION (user_data);
+ username = NULL;
+ password = NULL;
+ domain = NULL;
+
+ handled = g_mount_source_ask_password_finish (source,
+ res,
+ &aborted,
+ &username,
+ &password,
+ &domain,
+ NULL,
+ &password_save);
+
+ if (!handled)
+ result = G_MOUNT_OPERATION_UNHANDLED;
+ else if (aborted)
+ result = G_MOUNT_OPERATION_ABORTED;
+ else
+ {
+ result = G_MOUNT_OPERATION_HANDLED;
+
+ if (password)
+ g_mount_operation_set_password (op, password);
+ if (username)
+ g_mount_operation_set_username (op, username);
+ if (domain)
+ g_mount_operation_set_domain (op, domain);
+ g_mount_operation_set_password_save (op, password_save);
+ }
+
+ g_mount_operation_reply (op, result);
+ g_object_unref (op);
+}
+
+static gboolean
+op_ask_password (GMountOperation *op,
+ const char *message,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ GMountSource *mount_source)
+{
+ g_mount_source_ask_password_async (mount_source,
+ message,
+ default_user,
+ default_domain,
+ flags,
+ op_ask_password_reply,
+ g_object_ref (op));
+ return TRUE;
+}
+
+typedef struct AskQuestionData AskQuestionData;
+
+struct AskQuestionData {
+
+ /* results: */
+ gboolean aborted;
+ guint32 choice;
+};
+
+/* the callback from dbus -> main thread */
+static void
+ask_question_reply (DBusMessage *reply,
+ GError *error,
+ gpointer _data)
+{
+ GSimpleAsyncResult *result;
+ AskQuestionData *data;
+ dbus_bool_t handled, aborted;
+ guint32 choice;
+ DBusMessageIter iter;
+
+ result = G_SIMPLE_ASYNC_RESULT (_data);
+ handled = TRUE;
+
+ data = g_new0 (AskQuestionData, 1);
+ g_simple_async_result_set_op_res_gpointer (result, data, g_free);
+
+ if (reply == NULL)
+ {
+ data->aborted = TRUE;
+ }
+ else
+ {
+ dbus_message_iter_init (reply, &iter);
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &aborted,
+ DBUS_TYPE_UINT32, &choice,
+ 0))
+ data->aborted = TRUE;
+ else
+ {
+ data->aborted = aborted;
+ data->choice = choice;
+ }
+ }
+
+ if (handled == FALSE)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
+ }
+
+ g_simple_async_result_complete (result);
+}
+
+gboolean
+g_mount_source_ask_question (GMountSource *source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ gboolean *aborted_out,
+ gint *choice_out)
+{
+ gint choice;
+ gboolean handled, aborted;
+ AskSyncData data = {NULL};
+
+ data.mutex = g_mutex_new ();
+ data.cond = g_cond_new ();
+
+ g_mutex_lock (data.mutex);
+
+ g_mount_source_ask_question_async (source,
+ message,
+ choices,
+ n_choices,
+ ask_reply_sync,
+ &data);
+
+ g_cond_wait(data.cond, data.mutex);
+ g_mutex_unlock (data.mutex);
+
+ g_cond_free (data.cond);
+ g_mutex_free (data.mutex);
+
+ handled = g_mount_source_ask_question_finish (source,
+ data.result,
+ &aborted,
+ &choice);
+
+ g_object_unref (data.result);
+
+ if (aborted_out)
+ *aborted_out = aborted;
+
+ if (choice_out)
+ *choice_out = choice;
+
+ return handled;
+}
+
+void
+g_mount_source_ask_question_async (GMountSource *source,
+ const char *message_string,
+ const char **choices,
+ gint n_choices,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ DBusMessage *message;
+
+ /* If no dbus id specified, reply that we weren't handled */
+ if (source->dbus_id[0] == 0)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (source),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal Error");
+ return;
+ }
+
+ if (message_string == NULL)
+ message_string = "";
+
+ message = dbus_message_new_method_call (source->dbus_id,
+ source->obj_path,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION);
+
+ _g_dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ choices, n_choices,
+ 0);
+
+ result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+ g_mount_source_ask_question_async);
+ /* 30 minute timeout */
+ _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
+ ask_question_reply, result);
+ dbus_message_unref (message);
+
+}
+
+gboolean
+g_mount_source_ask_question_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ gint *choice_out)
+{
+ AskQuestionData *data, def= { FALSE, };
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, NULL))
+ data = &def;
+ else
+ data = (AskQuestionData *) g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (aborted)
+ *aborted = data->aborted;
+
+ if (choice_out)
+ *choice_out = data->choice;
+
+ return data != &def;
+}
+
+static void
+op_ask_question_reply (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GMountOperationResult result;
+ GMountOperation *op;
+ GMountSource *source;
+ gboolean handled, aborted;
+ gint choice;
+
+ source = G_MOUNT_SOURCE (source_object);
+ op = G_MOUNT_OPERATION (user_data);
+
+ handled = g_mount_source_ask_question_finish (source,
+ res,
+ &aborted,
+ &choice);
+
+ if (!handled)
+ result = G_MOUNT_OPERATION_UNHANDLED;
+ else if (aborted)
+ result = G_MOUNT_OPERATION_ABORTED;
+ else
+ {
+ result = G_MOUNT_OPERATION_HANDLED;
+ g_mount_operation_set_choice (op, choice);
+ }
+
+ g_mount_operation_reply (op, result);
+ g_object_unref (op);
+}
+
+static gboolean
+op_ask_question (GMountOperation *op,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ GMountSource *mount_source)
+{
+ g_mount_source_ask_question_async (mount_source,
+ message,
+ choices,
+ n_choices,
+ op_ask_question_reply,
+ g_object_ref (op));
+ return TRUE;
+}
+
+GMountOperation *
+g_mount_source_get_operation (GMountSource *mount_source)
+{
+ GMountOperation *op;
+
+ op = g_mount_operation_new ();
+ g_object_set_data_full (G_OBJECT (op), "source",
+ g_object_ref (mount_source),
+ g_object_unref);
+
+
+ g_signal_connect (op, "ask_password", (GCallback)op_ask_password, mount_source);
+ g_signal_connect (op, "ask_question", (GCallback)op_ask_question, mount_source);
+
+ return op;
+}
diff --git a/trunk/common/gmountsource.h b/trunk/common/gmountsource.h
new file mode 100644
index 00000000..e4298357
--- /dev/null
+++ b/trunk/common/gmountsource.h
@@ -0,0 +1,115 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_SOURCE_H__
+#define __G_MOUNT_SOURCE_H__
+
+#include <glib-object.h>
+#include <gmountspec.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT_SOURCE (g_mount_source_get_type ())
+#define G_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_SOURCE, GMountSource))
+#define G_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_SOURCE, GMountSourceClass))
+#define G_IS_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_SOURCE))
+#define G_IS_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_SOURCE))
+#define G_MOUNT_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_SOURCE, GMountSourceClass))
+
+typedef struct _GMountSource GMountSource;
+typedef struct _GMountSourceClass GMountSourceClass;
+
+struct _GMountSourceClass
+{
+ GObjectClass parent_class;
+};
+
+typedef void (*RequestMountSpecCallback) (GMountSource *source,
+ GMountSpec *mount_spec,
+ GError *error,
+ gpointer data);
+
+GType g_mount_source_get_type (void) G_GNUC_CONST;
+
+GMountSource *g_mount_source_new (const char *dbus_id,
+ const char *obj_path);
+GMountSource *g_mount_source_new_dummy (void);
+void g_mount_source_to_dbus (GMountSource *source,
+ DBusMessage *message);
+gboolean g_mount_source_ask_password (GMountSource *mount_source,
+ const char *message,
+ const char *initial_user,
+ const char *initial_domain,
+ GAskPasswordFlags flags,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out);
+
+void g_mount_source_ask_password_async (GMountSource *mount_source,
+ const char *message,
+ const char *initial_user,
+ const char *initial_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out);
+
+gboolean g_mount_source_ask_question (GMountSource *mount_source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ gboolean *aborted,
+ gint *choice_out);
+
+void g_mount_source_ask_question_async (GMountSource *mount_source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_mount_source_ask_question_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ gint *choice_out);
+
+
+const char * g_mount_source_get_dbus_id (GMountSource *mount_source);
+const char * g_mount_source_get_obj_path (GMountSource *mount_source);
+
+GMountOperation *g_mount_source_get_operation (GMountSource *mount_source);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_SOURCE_H__ */
diff --git a/trunk/common/gmountspec.c b/trunk/common/gmountspec.c
new file mode 100644
index 00000000..bee872fc
--- /dev/null
+++ b/trunk/common/gmountspec.c
@@ -0,0 +1,637 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gdbusutils.h"
+#include "gmountspec.h"
+
+static GHashTable *unique_hash = NULL;
+G_LOCK_DEFINE_STATIC(unique_hash);
+
+static int
+item_compare (const void *_a, const void *_b)
+{
+ const GMountSpecItem *a = _a;
+ const GMountSpecItem *b = _b;
+
+ return strcmp (a->key, b->key);
+}
+
+GMountSpec *
+g_mount_spec_new (const char *type)
+{
+ GMountSpec *spec;
+
+ spec = g_new0 (GMountSpec, 1);
+ spec->ref_count = 1;
+ spec->items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem));
+ spec->mount_prefix = g_strdup ("/");
+
+ if (type != NULL)
+ g_mount_spec_set (spec, "type", type);
+
+ return spec;
+}
+
+/* Takes ownership of passed in data */
+GMountSpec *
+g_mount_spec_new_from_data (GArray *items,
+ char *mount_prefix)
+{
+ GMountSpec *spec;
+
+ spec = g_new0 (GMountSpec, 1);
+ spec->ref_count = 1;
+ spec->items = items;
+ if (mount_prefix == NULL)
+ spec->mount_prefix = g_strdup ("/");
+ else
+ spec->mount_prefix = mount_prefix;
+
+ g_array_sort (spec->items, item_compare);
+
+ return spec;
+}
+
+GMountSpec *
+g_mount_spec_get_unique_for (GMountSpec *spec)
+{
+ GMountSpec *unique_spec;
+
+ if (spec->is_unique)
+ return g_mount_spec_ref (spec);
+
+ G_LOCK (unique_hash);
+
+ if (unique_hash == NULL)
+ unique_hash = g_hash_table_new (g_mount_spec_hash, (GEqualFunc)g_mount_spec_equal);
+
+ unique_spec = g_hash_table_lookup (unique_hash, spec);
+
+ if (unique_spec == NULL)
+ {
+ spec->is_unique = TRUE;
+ g_hash_table_insert (unique_hash, spec, spec);
+ unique_spec = spec;
+ }
+
+ g_mount_spec_ref (unique_spec);
+
+ G_UNLOCK (unique_hash);
+
+ return unique_spec;
+}
+
+void
+g_mount_spec_set_mount_prefix (GMountSpec *spec,
+ const char *mount_prefix)
+{
+ g_free (spec->mount_prefix);
+ spec->mount_prefix = g_strdup (mount_prefix);
+}
+
+
+static void
+add_item (GMountSpec *spec,
+ const char *key,
+ char *value)
+{
+ GMountSpecItem item;
+
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ item.key = g_strdup (key);
+ item.value = value;
+
+ g_array_append_val (spec->items, item);
+}
+
+
+void
+g_mount_spec_set_with_len (GMountSpec *spec,
+ const char *key,
+ const char *value,
+ int value_len)
+{
+ int i;
+ char *value_copy;
+
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ if (value_len == -1)
+ value_copy = g_strdup (value);
+ else
+ value_copy = g_strndup (value, value_len);
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ if (strcmp (item->key, key) == 0)
+ {
+ g_free (item->value);
+ item->value = value_copy;
+ return;
+ }
+ }
+
+ add_item (spec, key, value_copy);
+ g_array_sort (spec->items, item_compare);
+}
+
+void
+g_mount_spec_set (GMountSpec *spec,
+ const char *key,
+ const char *value)
+{
+ g_mount_spec_set_with_len (spec, key, value, -1);
+}
+
+
+GMountSpec *
+g_mount_spec_copy (GMountSpec *spec)
+{
+ GMountSpec *copy;
+ int i;
+
+ copy = g_mount_spec_new (NULL);
+ g_mount_spec_set_mount_prefix (copy, spec->mount_prefix);
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ g_mount_spec_set (copy, item->key, item->value);
+ }
+
+ return copy;
+}
+
+GMountSpec *
+g_mount_spec_ref (GMountSpec *spec)
+{
+ g_atomic_int_inc (&spec->ref_count);
+ return spec;
+}
+
+
+void
+g_mount_spec_unref (GMountSpec *spec)
+{
+ int i;
+
+ if (g_atomic_int_dec_and_test (&spec->ref_count))
+ {
+ G_LOCK (unique_hash);
+ if (unique_hash != NULL &&
+ spec->is_unique)
+ g_hash_table_remove (unique_hash, spec);
+ G_UNLOCK (unique_hash);
+
+ g_free (spec->mount_prefix);
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ g_free (item->key);
+ g_free (item->value);
+ }
+ g_array_free (spec->items, TRUE);
+
+ g_free (spec);
+ }
+}
+
+GMountSpec *
+g_mount_spec_from_dbus (DBusMessageIter *iter)
+{
+ GMountSpec *spec;
+ DBusMessageIter array_iter, struct_iter, spec_iter;
+ const char *key;
+ char *value;
+ char *mount_prefix;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &spec_iter);
+
+ mount_prefix = NULL;
+ if (!_g_dbus_message_iter_get_args (&spec_iter, NULL,
+ G_DBUS_TYPE_CSTRING, &mount_prefix,
+ 0))
+ return NULL;
+
+ spec = g_mount_spec_new (NULL);
+ g_free (spec->mount_prefix);
+ spec->mount_prefix = mount_prefix;
+
+ if (dbus_message_iter_get_arg_type (&spec_iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type (&spec_iter) != DBUS_TYPE_STRUCT)
+ {
+ g_mount_spec_unref (spec);
+ return NULL;
+ }
+
+ dbus_message_iter_recurse (&spec_iter, &array_iter);
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ dbus_message_iter_recurse (&array_iter, &struct_iter);
+ if (_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &key,
+ G_DBUS_TYPE_CSTRING, &value,
+ 0))
+ add_item (spec, key, value);
+ dbus_message_iter_next (&array_iter);
+ }
+
+ dbus_message_iter_next (iter);
+
+ /* Sort on key */
+ g_array_sort (spec->items, item_compare);
+
+ return spec;
+}
+
+void
+g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
+ GMountSpec *spec,
+ const char *path)
+{
+ DBusMessageIter spec_iter, array_iter, item_iter;
+ int i;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &spec_iter))
+ _g_dbus_oom ();
+
+ _g_dbus_message_iter_append_cstring (&spec_iter, path ? path : "");
+
+ if (!dbus_message_iter_open_container (&spec_iter,
+ DBUS_TYPE_ARRAY,
+ G_MOUNT_SPEC_ITEM_TYPE_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ if (!dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &item_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&item_iter, DBUS_TYPE_STRING,
+ &item->key))
+ _g_dbus_oom ();
+ _g_dbus_message_iter_append_cstring (&item_iter, item->value);
+
+ if (!dbus_message_iter_close_container (&array_iter, &item_iter))
+ _g_dbus_oom ();
+
+ }
+
+ if (!dbus_message_iter_close_container (&spec_iter, &array_iter))
+ _g_dbus_oom ();
+
+
+
+ if (!dbus_message_iter_close_container (iter, &spec_iter))
+ _g_dbus_oom ();
+
+}
+
+void
+g_mount_spec_to_dbus (DBusMessageIter *iter,
+ GMountSpec *spec)
+{
+ g_mount_spec_to_dbus_with_path (iter, spec, spec->mount_prefix);
+}
+
+static gboolean
+items_equal (GArray *a,
+ GArray *b)
+{
+ int i;
+
+ if (a->len != b->len)
+ return FALSE;
+
+ for (i = 0; i < a->len; i++)
+ {
+ GMountSpecItem *item_a = &g_array_index (a, GMountSpecItem, i);
+ GMountSpecItem *item_b = &g_array_index (b, GMountSpecItem, i);
+
+ if (strcmp (item_a->key, item_b->key) != 0)
+ return FALSE;
+ if (strcmp (item_a->value, item_b->value) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+path_has_prefix (const char *path,
+ const char *prefix)
+{
+ int prefix_len;
+
+ if (prefix == NULL)
+ return TRUE;
+
+ prefix_len = strlen (prefix);
+
+ if (strncmp (path, prefix, prefix_len) == 0 &&
+ (prefix_len == 0 || /* empty prefix always matches */
+ prefix[prefix_len - 1] == '/' || /* last char in prefix was a /, so it must be in path too */
+ path[prefix_len] == 0 ||
+ path[prefix_len] == '/'))
+ return TRUE;
+
+ return FALSE;
+}
+
+guint
+g_mount_spec_hash (gconstpointer _mount)
+{
+ GMountSpec *mount = (GMountSpec *) _mount;
+ guint hash;
+ int i;
+
+ hash = 0;
+ if (mount->mount_prefix)
+ hash ^= g_str_hash (mount->mount_prefix);
+
+ for (i = 0; i < mount->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (mount->items, GMountSpecItem, i);
+ hash ^= g_str_hash (item->value);
+ }
+
+ return hash;
+}
+
+gboolean
+g_mount_spec_equal (GMountSpec *mount1,
+ GMountSpec *mount2)
+{
+ return items_equal (mount1->items, mount2->items) &&
+ ((mount1->mount_prefix == mount2->mount_prefix) ||
+ (mount1->mount_prefix != NULL && mount2->mount_prefix != NULL &&
+ strcmp (mount1->mount_prefix, mount2->mount_prefix) == 0));
+}
+
+gboolean
+g_mount_spec_match_with_path (GMountSpec *mount,
+ GMountSpec *spec,
+ const char *path)
+{
+ if (items_equal (mount->items, spec->items) &&
+ path_has_prefix (path, mount->mount_prefix))
+ return TRUE;
+ return FALSE;
+}
+
+gboolean
+g_mount_spec_match (GMountSpec *mount,
+ GMountSpec *path)
+{
+ return g_mount_spec_match_with_path (mount, path, path->mount_prefix);
+}
+
+const char *
+g_mount_spec_get (GMountSpec *spec,
+ const char *key)
+{
+ int i;
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ if (strcmp (item->key, key) == 0)
+ return item->value;
+ }
+
+ return NULL;
+}
+
+const char *
+g_mount_spec_get_type (GMountSpec *spec)
+{
+ return g_mount_spec_get (spec, "type");
+}
+
+char *
+g_mount_spec_to_string (GMountSpec *spec)
+{
+ GString *str;
+ char *k;
+ char *v;
+ int i;
+
+ if (spec == NULL)
+ return g_strdup ("(null)");
+
+ str = g_string_new ("");
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ k = g_uri_escape_string (item->key, NULL, TRUE);
+ v = g_uri_escape_string (item->value, NULL, TRUE);
+ g_string_append_printf (str, "%s=%s,", k, v);
+ g_free (k);
+ g_free (v);
+ }
+ k = g_uri_escape_string ("__mount_prefix", NULL, TRUE);
+ v = g_uri_escape_string (spec->mount_prefix, NULL, TRUE);
+ g_string_append_printf (str, "%s=%s", k, v);
+ g_free (k);
+ g_free (v);
+
+ return g_string_free (str, FALSE);
+}
+
+GMountSpec *
+g_mount_spec_new_from_string (const gchar *str,
+ GError **error)
+{
+ GArray *items;
+ GMountSpec *mount_spec;
+ char **kv_pairs;
+ char *mount_prefix;
+ int i;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ mount_spec = NULL;
+ mount_prefix = NULL;
+ items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem));
+
+ kv_pairs = g_strsplit (str, ",", 0);
+ for (i = 0; kv_pairs[i] != NULL; i++)
+ {
+ char **tokens;
+ GMountSpecItem item;
+
+ tokens = g_strsplit (kv_pairs[i], "=", 0);
+ if (g_strv_length (tokens) != 2)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "Encountered invalid key/value pair '%s' while decoding GMountSpec",
+ kv_pairs[i]);
+ g_strfreev (tokens);
+ g_strfreev (kv_pairs);
+ goto fail;
+ }
+
+ item.key = g_uri_unescape_string (tokens[0], NULL);
+ item.value = g_uri_unescape_string (tokens[1], NULL);
+
+ if (strcmp (item.key, "__mount_prefix") == 0)
+ {
+ g_free (item.key);
+ mount_prefix = item.value;
+ }
+ else
+ {
+ g_array_append_val (items, item);
+ }
+
+ g_strfreev (tokens);
+ }
+ g_strfreev (kv_pairs);
+
+ if (mount_prefix == NULL)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "Didn't find __mount_prefix while decoding '%s' GMountSpec",
+ str);
+ goto fail;
+ }
+
+ /* this constructor takes ownership of the data we pass in */
+ mount_spec = g_mount_spec_new_from_data (items,
+ mount_prefix);
+
+ return mount_spec;
+
+ fail:
+ for (i = 0; i < items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (items, GMountSpecItem, i);
+ g_free (item->key);
+ g_free (item->value);
+ }
+ g_array_free (items, TRUE);
+ g_free (mount_prefix);
+ return NULL;
+}
+
+
+char *
+g_mount_spec_canonicalize_path (const char *path)
+{
+ char *canon, *start, *p, *q;
+
+ if (*path != '/')
+ canon = g_strconcat ("/", path, NULL);
+ else
+ canon = g_strdup (path);
+
+ /* Skip initial slash */
+ start = canon + 1;
+
+ p = start;
+ while (*p != 0)
+ {
+ if (p[0] == '.' && (p[1] == 0 || p[1] == '/'))
+ {
+ memmove (p, p+1, strlen (p+1)+1);
+ }
+ else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ {
+ q = p + 2;
+ /* Skip previous separator */
+ p = p - 2;
+ if (p < start)
+ p = start;
+ while (p > start && *p != '/')
+ p--;
+ if (*p == '/')
+ p++;
+ memmove (p, q, strlen (q)+1);
+ }
+ else
+ {
+ /* Skip until next separator */
+ while (*p != 0 && *p != '/')
+ p++;
+
+ /* Keep one separator */
+ if (*p != 0)
+ p++;
+ }
+
+ /* Remove additional separators */
+ q = p;
+ while (*q && *q == '/')
+ q++;
+
+ if (p != q)
+ memmove (p, q, strlen (q)+1);
+ }
+
+ /* Remove trailing slashes */
+ if (p > start && *(p-1) == '/')
+ *(p-1) = 0;
+
+ return canon;
+}
+
+GType
+g_type_mount_spec_get_gtype (void)
+{
+ static GType type_id = 0;
+
+ if (type_id == 0)
+ type_id = g_boxed_type_register_static (g_intern_static_string ("GMountSpec"),
+ (GBoxedCopyFunc) g_mount_spec_ref,
+ (GBoxedFreeFunc) g_mount_spec_unref);
+ return type_id;
+}
diff --git a/trunk/common/gmountspec.h b/trunk/common/gmountspec.h
new file mode 100644
index 00000000..879c39b8
--- /dev/null
+++ b/trunk/common/gmountspec.h
@@ -0,0 +1,109 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_SPEC_H__
+#define __G_MOUNT_SPEC_H__
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_STRING_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
+
+#define G_MOUNT_SPEC_ITEM_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+#define G_MOUNT_SPEC_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING G_MOUNT_SPEC_ITEM_TYPE_AS_STRING
+
+#define G_MOUNT_SPEC_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_MOUNT_SPEC_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+typedef struct {
+ char *key;
+ char *value;
+} GMountSpecItem;
+
+typedef struct {
+ volatile int ref_count;
+ GArray *items;
+ char *mount_prefix;
+ gboolean is_unique;
+} GMountSpec;
+
+GMountSpec *g_mount_spec_new (const char *type);
+GMountSpec *g_mount_spec_new_from_data (GArray *items,
+ char *mount_prefix);
+GMountSpec *g_mount_spec_ref (GMountSpec *spec);
+void g_mount_spec_unref (GMountSpec *spec);
+GMountSpec *g_mount_spec_get_unique_for (GMountSpec *spec);
+GMountSpec *g_mount_spec_copy (GMountSpec *spec);
+GMountSpec *g_mount_spec_from_dbus (DBusMessageIter *iter);
+void g_mount_spec_to_dbus (DBusMessageIter *iter,
+ GMountSpec *spec);
+void g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
+ GMountSpec *spec,
+ const char *path);
+void g_mount_spec_set_mount_prefix (GMountSpec *spec,
+ const char *mount_prefix);
+void g_mount_spec_set (GMountSpec *spec,
+ const char *key,
+ const char *value);
+void g_mount_spec_set_with_len (GMountSpec *spec,
+ const char *key,
+ const char *value,
+ int value_len);
+guint g_mount_spec_hash (gconstpointer mount);
+gboolean g_mount_spec_equal (GMountSpec *mount1,
+ GMountSpec *mount2);
+gboolean g_mount_spec_match (GMountSpec *mount,
+ GMountSpec *path);
+gboolean g_mount_spec_match_with_path (GMountSpec *mount,
+ GMountSpec *spec,
+ const char *path);
+const char *g_mount_spec_get (GMountSpec *spec,
+ const char *key);
+const char *g_mount_spec_get_type (GMountSpec *spec);
+
+char * g_mount_spec_to_string (GMountSpec *spec);
+
+GMountSpec *g_mount_spec_new_from_string (const gchar *str,
+ GError **error);
+
+char * g_mount_spec_canonicalize_path (const char *path);
+
+
+#define G_TYPE_MOUNT_SPEC (g_type_mount_spec_get_gtype ())
+GType g_type_mount_spec_get_gtype (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+
+#endif /* __G_MOUNT_SPEC_H__ */
diff --git a/trunk/common/gmounttracker.c b/trunk/common/gmounttracker.c
new file mode 100644
index 00000000..28550681
--- /dev/null
+++ b/trunk/common/gmounttracker.c
@@ -0,0 +1,634 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gmounttracker.h>
+#include <gdbusutils.h>
+#include <gvfsdaemonprotocol.h>
+
+enum {
+ MOUNTED,
+ UNMOUNTED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_CONNECTION
+};
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+#define I_(string) g_intern_static_string (string)
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _GMountTracker
+{
+ GObject parent_instance;
+
+ GMutex *lock;
+ GList *mounts;
+ DBusConnection *connection;
+};
+
+G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT)
+
+static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data);
+static GObject* g_mount_tracker_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+static void g_mount_tracker_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void g_mount_tracker_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+gboolean
+g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2)
+{
+ return
+ strcmp (info1->dbus_id, info2->dbus_id) == 0 &&
+ strcmp (info1->object_path, info2->object_path) == 0;
+}
+
+GMountInfo *
+g_mount_info_dup (GMountInfo *info)
+{
+ GMountInfo *copy;
+
+ copy = g_new (GMountInfo, 1);
+ copy->ref_count = 1;
+ copy->display_name = g_strdup (info->display_name);
+ copy->stable_name = g_strdup (info->stable_name);
+ copy->x_content_types = g_strdup (info->x_content_types);
+ copy->icon = g_object_ref (info->icon);
+ copy->dbus_id = g_strdup (info->dbus_id);
+ copy->object_path = g_strdup (info->object_path);
+ copy->mount_spec = g_mount_spec_copy (info->mount_spec);
+ copy->user_visible = info->user_visible;
+ copy->prefered_filename_encoding = g_strdup (info->prefered_filename_encoding);
+ copy->fuse_mountpoint = g_strdup (info->fuse_mountpoint);
+
+ return copy;
+}
+
+GMountInfo *
+g_mount_info_ref (GMountInfo *info)
+{
+ g_atomic_int_inc (&info->ref_count);
+ return info;
+}
+
+void
+g_mount_info_unref (GMountInfo *info)
+{
+ if (g_atomic_int_dec_and_test (&info->ref_count))
+ {
+ g_free (info->display_name);
+ g_free (info->stable_name);
+ g_free (info->x_content_types);
+ g_object_unref (info->icon);
+ g_free (info->dbus_id);
+ g_free (info->object_path);
+ g_mount_spec_unref (info->mount_spec);
+ g_free (info->prefered_filename_encoding);
+ g_free (info->fuse_mountpoint);
+ g_free (info);
+ }
+}
+
+const char *
+g_mount_info_resolve_path (GMountInfo *info,
+ const char *path)
+{
+ const char *new_path;
+ int len;
+
+ if (info->mount_spec->mount_prefix != NULL &&
+ info->mount_spec->mount_prefix[0] != 0)
+ {
+ len = strlen (info->mount_spec->mount_prefix);
+ if (info->mount_spec->mount_prefix[len-1] == '/')
+ len--;
+ new_path = path + len;
+ }
+ else
+ new_path = path;
+
+ if (new_path == NULL ||
+ new_path[0] == 0)
+ new_path = "/";
+
+ return new_path;
+}
+
+GMountInfo *
+g_mount_info_from_dbus (DBusMessageIter *iter)
+{
+ DBusMessageIter struct_iter;
+ GMountInfo *info;
+ GMountSpec *mount_spec;
+ dbus_bool_t user_visible;
+ char *display_name;
+ char *stable_name;
+ char *x_content_types;
+ char *icon_str;
+ char *prefered_filename_encoding;
+ char *dbus_id;
+ char *obj_path;
+ char *fuse_mountpoint;
+ GIcon *icon;
+ GError *error;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ DBUS_TYPE_STRING, &display_name,
+ DBUS_TYPE_STRING, &stable_name,
+ DBUS_TYPE_STRING, &x_content_types,
+ DBUS_TYPE_STRING, &icon_str,
+ DBUS_TYPE_STRING, &prefered_filename_encoding,
+ DBUS_TYPE_BOOLEAN, &user_visible,
+ G_DBUS_TYPE_CSTRING, &fuse_mountpoint,
+ 0))
+ return NULL;
+
+ mount_spec = g_mount_spec_from_dbus (&struct_iter);
+ if (mount_spec == NULL) {
+ g_free (fuse_mountpoint);
+ return NULL;
+ }
+
+ if (icon_str == NULL || strlen (icon_str) == 0)
+ icon_str = "drive-removable-media";
+ error = NULL;
+ icon = g_icon_new_for_string (icon_str, &error);
+ if (icon == NULL)
+ {
+ g_warning ("Malformed icon string '%s': %s", icon_str, error->message);
+ g_error_free (error);
+ icon = g_themed_icon_new ("gtk-missing-image"); /* TODO: maybe choose a better name */
+ }
+
+ info = g_new0 (GMountInfo, 1);
+ info->ref_count = 1;
+ info->display_name = g_strdup (display_name);
+ info->stable_name = g_strdup (stable_name);
+ info->x_content_types = g_strdup (x_content_types);
+ info->icon = icon;
+ info->dbus_id = g_strdup (dbus_id);
+ info->object_path = g_strdup (obj_path);
+ info->mount_spec = mount_spec;
+ info->user_visible = user_visible;
+ info->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
+ info->fuse_mountpoint = fuse_mountpoint;
+
+ return info;
+}
+
+
+static void
+g_mount_tracker_finalize (GObject *object)
+{
+ GMountTracker *tracker;
+
+ tracker = G_MOUNT_TRACKER (object);
+
+ if (tracker->lock)
+ g_mutex_free (tracker->lock);
+
+ g_list_foreach (tracker->mounts,
+ (GFunc)g_mount_info_unref, NULL);
+ g_list_free (tracker->mounts);
+
+ dbus_connection_remove_filter (tracker->connection, g_mount_tracker_filter_func, tracker);
+
+
+ dbus_bus_remove_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_remove_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+
+ dbus_connection_unref (tracker->connection);
+
+ if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object);
+}
+
+static void
+g_mount_tracker_class_init (GMountTrackerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mount_tracker_finalize;
+ gobject_class->constructor = g_mount_tracker_constructor;
+ gobject_class->set_property = g_mount_tracker_set_property;
+ gobject_class->get_property = g_mount_tracker_get_property;
+
+ signals[MOUNTED] = g_signal_new (I_("mounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, mounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[UNMOUNTED] = g_signal_new (I_("unmounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, unmounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ g_object_class_install_property (gobject_class,
+ PROP_CONNECTION,
+ g_param_spec_pointer ("connection",
+ P_("DBus connection"),
+ P_("The dbus connection to use for ipc."),
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+
+}
+
+static void
+g_mount_tracker_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GMountTracker *tracker = G_MOUNT_TRACKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ if (tracker->connection)
+ dbus_connection_unref (tracker->connection);
+ tracker->connection = NULL;
+ if (g_value_get_pointer (value))
+ tracker->connection = dbus_connection_ref (g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_mount_tracker_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GMountTracker *tracker = G_MOUNT_TRACKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_pointer (value, tracker->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GList *
+g_mount_tracker_find (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ if (g_mount_info_equal (info, (GMountInfo *)l->data))
+ return l;
+ }
+
+ return NULL;
+}
+
+static void
+g_mount_tracker_add_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ /* Don't add multiple times */
+ if (g_mount_tracker_find (tracker, info))
+ {
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+ return;
+ }
+
+ tracker->mounts = g_list_prepend (tracker->mounts, g_mount_info_ref (info));
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ g_signal_emit (tracker, signals[MOUNTED], 0, info);
+}
+
+static void
+g_mount_tracker_remove_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+ GMountInfo *old_info;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ l = g_mount_tracker_find (tracker, info);
+
+ /* Don't remove multiple times */
+ if (l == NULL)
+ {
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+ return;
+ }
+
+ old_info = l->data;
+
+ tracker->mounts = g_list_delete_link (tracker->mounts, l);
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ g_signal_emit (tracker, signals[UNMOUNTED], 0, old_info);
+ g_mount_info_unref (old_info);
+}
+
+static void
+list_mounts_reply (GMountTracker *tracker,
+ DBusMessage *reply)
+{
+ DBusMessageIter iter, array_iter;
+ GMountInfo *info;
+ gboolean b;
+
+ b = dbus_message_iter_init (reply, &iter);
+ if (b && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY)
+ {
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ do
+ {
+ info = g_mount_info_from_dbus (&array_iter);
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+ while (dbus_message_iter_next (&array_iter));
+ }
+ else
+ {
+ /* list_mounts_reply problem - gvfsd not running? */
+ }
+}
+
+static DBusHandlerResult
+g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ GMountTracker *tracker = data;
+ GMountInfo *info;
+ DBusMessageIter iter;
+
+ if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+ else if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_remove_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* Called after construction when the construct properties (like connection) are set */
+static void
+init_connection (GMountTracker *tracker)
+{
+ DBusMessage *message, *reply;
+
+ if (tracker->connection == NULL)
+ tracker->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS);
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_set_auto_start (message, TRUE);
+
+ reply = dbus_connection_send_with_reply_and_block (tracker->connection, message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ NULL);
+ dbus_message_unref (message);
+
+ if (reply != NULL)
+ {
+ list_mounts_reply (tracker, reply);
+ dbus_message_unref (reply);
+ }
+
+ dbus_connection_add_filter (tracker->connection, g_mount_tracker_filter_func, tracker, NULL);
+
+ dbus_bus_add_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_add_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+}
+
+static void
+g_mount_tracker_init (GMountTracker *tracker)
+{
+ if (g_thread_supported ())
+ tracker->lock = g_mutex_new ();
+}
+
+
+static GObject*
+g_mount_tracker_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GMountTracker *tracker;
+
+ object = (* G_OBJECT_CLASS (g_mount_tracker_parent_class)->constructor) (type,
+ n_construct_properties,
+ construct_params);
+
+ tracker = G_MOUNT_TRACKER (object);
+
+ init_connection (tracker);
+
+ return object;
+}
+
+GMountTracker *
+g_mount_tracker_new (DBusConnection *connection)
+{
+ GMountTracker *tracker;
+
+ tracker = g_object_new (G_TYPE_MOUNT_TRACKER, "connection", connection, NULL);
+
+ return tracker;
+}
+
+GList *
+g_mount_tracker_list_mounts (GMountTracker *tracker)
+{
+ GList *res, *l;
+ GMountInfo *copy;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ res = NULL;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ copy = g_mount_info_ref (l->data);
+ res = g_list_prepend (res, copy);
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return g_list_reverse (res);
+}
+
+GMountInfo *
+g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec)
+{
+ GList *l;
+ GMountInfo *info, *found;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ found = NULL;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ info = l->data;
+
+ if (g_mount_spec_equal (info->mount_spec, mount_spec))
+ {
+ found = g_mount_info_ref (info);
+ break;
+ }
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return found;
+}
+
+
+gboolean
+g_mount_tracker_has_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec)
+{
+ GList *l;
+ GMountInfo *info;
+ gboolean found;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ found = FALSE;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ info = l->data;
+
+ if (g_mount_spec_equal (info->mount_spec, mount_spec))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return found;
+}
+
diff --git a/trunk/common/gmounttracker.h b/trunk/common/gmounttracker.h
new file mode 100644
index 00000000..efad24a9
--- /dev/null
+++ b/trunk/common/gmounttracker.h
@@ -0,0 +1,87 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_TRACKER_H__
+#define __G_MOUNT_TRACKER_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT_TRACKER (g_mount_tracker_get_type ())
+#define G_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_TRACKER, GMountTracker))
+#define G_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+#define G_IS_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_TRACKER))
+#define G_IS_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_TRACKER))
+#define G_MOUNT_TRACKER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+
+typedef struct _GMountTracker GMountTracker;
+typedef struct _GMountTrackerClass GMountTrackerClass;
+
+typedef struct {
+ volatile int ref_count;
+ char *display_name;
+ char *stable_name;
+ char *x_content_types;
+ GIcon *icon;
+ char *dbus_id;
+ char *object_path;
+ gboolean user_visible;
+ char *prefered_filename_encoding; /* NULL -> UTF8 */
+ char *fuse_mountpoint;
+ GMountSpec *mount_spec;
+} GMountInfo;
+
+struct _GMountTrackerClass
+{
+ GObjectClass parent_class;
+
+ void (*mounted) (GMountTracker *tracker,
+ GMountInfo *info);
+ void (*unmounted) (GMountTracker *tracker,
+ GMountInfo *info);
+};
+
+GType g_mount_tracker_get_type (void) G_GNUC_CONST;
+
+gboolean g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2);
+GMountInfo *g_mount_info_ref (GMountInfo *info);
+GMountInfo *g_mount_info_dup (GMountInfo *info);
+void g_mount_info_unref (GMountInfo *info);
+const char *g_mount_info_resolve_path (GMountInfo *info,
+ const char *path);
+
+GMountInfo * g_mount_info_from_dbus (DBusMessageIter *iter);
+
+GMountTracker *g_mount_tracker_new (DBusConnection *connection);
+GList * g_mount_tracker_list_mounts (GMountTracker *tracker);
+GMountInfo * g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec);
+gboolean g_mount_tracker_has_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_TRACKER_H__ */
diff --git a/trunk/common/gsysutils.c b/trunk/common/gsysutils.c
new file mode 100644
index 00000000..9dd8afa4
--- /dev/null
+++ b/trunk/common/gsysutils.c
@@ -0,0 +1,181 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <gio/gio.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gsysutils.h"
+
+int
+_g_socket_send_fd (int connection_fd,
+ int fd)
+{
+ struct msghdr msg;
+ struct iovec vec[1];
+ char buf[1] = {'x'};
+ char ccmsg[CMSG_SPACE (sizeof (fd))];
+ struct cmsghdr *cmsg;
+ int ret;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ vec[0].iov_base = buf;
+ vec[0].iov_len = 1;
+ msg.msg_iov = vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+ cmsg = CMSG_FIRSTHDR (&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN (sizeof(fd));
+ *(int*)CMSG_DATA (cmsg) = fd;
+ msg.msg_controllen = cmsg->cmsg_len;
+ msg.msg_flags = 0;
+
+ ret = sendmsg (connection_fd, &msg, 0);
+ return ret;
+}
+
+/* receive a file descriptor over file descriptor fd */
+int
+_g_socket_receive_fd (int socket_fd)
+{
+ struct msghdr msg;
+ struct iovec iov[1];
+ char buf[1];
+ int rv;
+ char ccmsg[CMSG_SPACE (sizeof(int))];
+ struct cmsghdr *cmsg;
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 1;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+
+ rv = recvmsg (socket_fd, &msg, 0);
+ if (rv == -1)
+ {
+ perror ("recvmsg");
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ if (cmsg == NULL)
+ return -1;
+
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ g_warning("got control message of unknown type %d",
+ cmsg->cmsg_type);
+ return -1;
+ }
+
+ return *(int*)CMSG_DATA(cmsg);
+}
+
+int
+_g_socket_connect (const char *address,
+ GError **error)
+{
+ int fd;
+ const char *path;
+ size_t path_len;
+ struct sockaddr_un addr;
+ gboolean abstract;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error creating socket: %s"),
+ g_strerror (errsv));
+ return -1;
+ }
+
+ if (g_str_has_prefix (address, "unix:abstract="))
+ {
+ path = address + strlen ("unix:abstract=");
+ abstract = TRUE;
+ }
+ else
+ {
+ path = address + strlen ("unix:path=");
+ abstract = FALSE;
+ }
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ path_len = strlen (path);
+
+ if (abstract)
+ {
+ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+ path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+ strncpy (&addr.sun_path[1], path, path_len);
+ }
+ else
+ {
+ strncpy (addr.sun_path, path, path_len);
+ }
+
+ if (connect (fd, (struct sockaddr*) &addr, G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error connecting to socket: %s"),
+ g_strerror (errsv));
+ close (fd);
+ return -1;
+ }
+
+ return fd;
+}
diff --git a/trunk/common/gsysutils.h b/trunk/common/gsysutils.h
new file mode 100644
index 00000000..f68a2642
--- /dev/null
+++ b/trunk/common/gsysutils.h
@@ -0,0 +1,39 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_SYS_UTILS_H__
+#define __G_SYS_UTILS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+int _g_socket_send_fd (int socket_fd,
+ int fd);
+int _g_socket_receive_fd (int socket_fd);
+int _g_socket_connect (const char *address,
+ GError **error);
+
+G_END_DECLS
+
+
+#endif /* __G_SYS_UTILS_H__ */
diff --git a/trunk/common/gvfsdaemonprotocol.c b/trunk/common/gvfsdaemonprotocol.c
new file mode 100644
index 00000000..c90a7ba2
--- /dev/null
+++ b/trunk/common/gvfsdaemonprotocol.c
@@ -0,0 +1,553 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib-object.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n-lib.h>
+#include <gvfsdaemonprotocol.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+
+static const char *
+get_object_signature (GObject *obj)
+{
+ if (G_IS_ICON (obj))
+ {
+ return
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+ }
+ return
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+}
+
+static void
+append_object (DBusMessageIter *iter, GObject *obj)
+{
+ DBusMessageIter obj_struct_iter;
+ guint32 v_uint32;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &obj_struct_iter))
+ _g_dbus_oom ();
+
+ /* version 1 and 2 are deprecated old themed-icon and file-icon values */
+ if (G_IS_ICON (obj))
+ {
+ char *data;
+
+ data = g_icon_to_string (G_ICON (obj));
+ v_uint32 = 3;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_STRING, &data))
+ _g_dbus_oom ();
+
+ g_free (data);
+ }
+ else
+ {
+ /* NULL or unknown type: */
+ if (obj != NULL)
+ g_warning ("Unknown attribute object type, ignoring");
+
+ v_uint32 = 0;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (iter, &obj_struct_iter))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_attribute_value_destroy (GFileAttributeType type,
+ GDbusAttributeValue *value)
+{
+ switch (type) {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ g_free (value->ptr);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ if (value->ptr)
+ g_object_unref (value->ptr);
+ break;
+ default:
+ break;
+ }
+}
+
+gpointer
+_g_dbus_attribute_as_pointer (GFileAttributeType type,
+ GDbusAttributeValue *value)
+{
+ switch (type) {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ return value->ptr;
+ default:
+ return (gpointer) value;
+ }
+}
+
+const char *
+_g_dbus_type_from_file_attribute_type (GFileAttributeType type)
+{
+ char *dbus_type;
+
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ dbus_type = DBUS_TYPE_STRING_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
+ dbus_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ dbus_type = DBUS_TYPE_UINT32_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ dbus_type = DBUS_TYPE_INT32_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ dbus_type = DBUS_TYPE_UINT64_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ dbus_type = DBUS_TYPE_INT64_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ dbus_type = DBUS_TYPE_STRUCT_AS_STRING;
+ break;
+ default:
+ dbus_type = NULL;
+ g_warning ("Invalid attribute type %u, ignoring\n", type);
+ break;
+ }
+
+ return dbus_type;
+}
+
+void
+_g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p)
+{
+ DBusMessageIter variant_iter, inner_struct_iter;
+ const char *dbus_type;
+ GObject *obj = NULL;
+
+ dbus_type = _g_dbus_type_from_file_attribute_type (type);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &inner_struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&inner_struct_iter,
+ DBUS_TYPE_STRING,
+ &attribute))
+ _g_dbus_oom ();
+
+ if (dbus_type[0] == DBUS_TYPE_STRUCT)
+ dbus_type = get_object_signature ((GObject *)value_p);
+
+ if (!dbus_message_iter_open_container (&inner_struct_iter,
+ DBUS_TYPE_VARIANT,
+ dbus_type,
+ &variant_iter))
+ _g_dbus_oom ();
+
+ if (dbus_type[0] == DBUS_TYPE_STRING)
+ {
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ DBUS_TYPE_STRING, &value_p))
+ _g_dbus_oom ();
+ }
+ else if (dbus_type[0] == DBUS_TYPE_ARRAY)
+ _g_dbus_message_iter_append_cstring (&variant_iter, (char *)value_p);
+ else if (dbus_type[0] == DBUS_STRUCT_BEGIN_CHAR)
+ append_object (&variant_iter, (GObject *)value_p);
+ else if (dbus_type[0] == DBUS_TYPE_BOOLEAN)
+ {
+ /* dbus bool is uint32, gboolean is just "int", convert */
+ dbus_bool_t bool = *(gboolean *)value_p;
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ dbus_type[0], &bool))
+ _g_dbus_oom ();
+ }
+ else
+ {
+ /* All other types have the same size as dbus types */
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ dbus_type[0], value_p))
+ _g_dbus_oom ();
+ }
+
+ if (obj)
+ g_object_unref (obj);
+
+ if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &inner_struct_iter))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *info)
+{
+ DBusMessageIter struct_iter, array_iter;
+ char **attributes;
+ int i;
+
+ attributes = g_file_info_list_attributes (info, NULL);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+
+ if (!dbus_message_iter_open_container (&struct_iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; attributes[i] != NULL; i++)
+ {
+ GFileAttributeType type;
+ gpointer value_p;
+
+ if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, NULL))
+ _g_dbus_append_file_attribute (&array_iter, attributes [i], type, value_p);
+ }
+
+ g_strfreev (attributes);
+
+ if (!dbus_message_iter_close_container (&struct_iter, &array_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &struct_iter))
+ _g_dbus_oom ();
+}
+
+gboolean
+_g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GDbusAttributeValue *value)
+{
+ char *str;
+ char **strs;
+ int n_elements;
+ DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter;
+ const gchar *attribute_temp;
+ dbus_uint32_t obj_type;
+ dbus_bool_t dbus_bool;
+ GObject *obj;
+
+ dbus_message_iter_recurse (iter, &inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING)
+ goto error;
+
+ dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp);
+ *attribute = g_strdup (attribute_temp);
+
+ dbus_message_iter_next (&inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT)
+ goto error;
+
+ dbus_message_iter_recurse (&inner_struct_iter, &variant_iter);
+
+ switch (dbus_message_iter_get_arg_type (&variant_iter))
+ {
+ case DBUS_TYPE_STRING:
+ *type = G_FILE_ATTRIBUTE_TYPE_STRING;
+ dbus_message_iter_get_basic (&variant_iter, &str);
+ value->ptr = g_strdup (str);
+ break;
+ case DBUS_TYPE_ARRAY:
+ if (dbus_message_iter_get_element_type (&variant_iter) != DBUS_TYPE_BYTE)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
+
+ dbus_message_iter_recurse (&variant_iter, &cstring_iter);
+ dbus_message_iter_get_fixed_array (&cstring_iter,
+ &str, &n_elements);
+ value->ptr = g_strndup (str, n_elements);
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_basic (&variant_iter, &dbus_bool);
+ value->boolean = dbus_bool;
+ *type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
+ break;
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT32;
+ break;
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT32;
+ break;
+ case DBUS_TYPE_UINT64:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT64;
+ break;
+ case DBUS_TYPE_INT64:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT64;
+ break;
+ case DBUS_TYPE_STRUCT:
+ dbus_message_iter_recurse (&variant_iter, &obj_iter);
+ if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
+
+ dbus_message_iter_get_basic (&obj_iter, &obj_type);
+ obj = NULL;
+
+ dbus_message_iter_next (&obj_iter);
+ /* 0 == NULL */
+
+ if (obj_type == 1)
+ {
+ /* Old deprecated G_THEMED_ICON */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &strs, &n_elements, 0))
+ {
+ obj = G_OBJECT (g_themed_icon_new_from_names (strs, n_elements));
+ g_strfreev (strs);
+ }
+ }
+ else if (obj_type == 2)
+ {
+ /* Old deprecated G_FILE_ICON, w/ local file */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ G_DBUS_TYPE_CSTRING, &str,
+ 0))
+ {
+ GFile *file = g_file_new_for_path (str);
+ obj = G_OBJECT (g_file_icon_new (file));
+ g_free (str);
+ }
+ }
+ else if (obj_type == 3)
+ {
+ /* serialized G_ICON */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ DBUS_TYPE_STRING, &str,
+ 0))
+ obj = (GObject *)g_icon_new_for_string (str, NULL);
+ }
+ else
+ {
+ /* NULL (or unsupported) */
+ if (obj_type != 0)
+ g_warning ("Unsupported object type in file attribute");
+ }
+
+ value->ptr = obj;
+ break;
+ default:
+ goto error;
+ }
+
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+GFileInfo *
+_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error)
+{
+ GFileInfo *info;
+ DBusMessageIter struct_iter, array_iter;
+ gchar *attribute;
+ GFileAttributeType type;
+ GDbusAttributeValue value;
+
+ info = g_file_info_new ();
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ goto error;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY)
+ goto error;
+
+ dbus_message_iter_recurse (&struct_iter, &array_iter);
+
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &type, &value))
+ goto error;
+
+ g_file_info_set_attribute (info, attribute, type, _g_dbus_attribute_as_pointer (type, &value));
+
+ g_free (attribute);
+ _g_dbus_attribute_value_destroy (type, &value);
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ dbus_message_iter_next (iter);
+ return info;
+
+ error:
+ g_object_unref (info);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid file info format"));
+ return NULL;
+}
+
+GFileAttributeInfoList *
+_g_dbus_get_attribute_info_list (DBusMessageIter *iter,
+ GError **error)
+{
+ GFileAttributeInfoList *list;
+ DBusMessageIter array_iter, struct_iter;
+ const char *name;
+ dbus_uint32_t type, flags;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type (iter) != DBUS_TYPE_STRUCT)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid attribute info list content"));
+ return NULL;
+ }
+
+ list = g_file_attribute_info_list_new ();
+
+ dbus_message_iter_recurse (iter, &array_iter);
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ dbus_message_iter_recurse (&array_iter, &struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_STRING)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &name);
+ dbus_message_iter_next (&struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &type);
+ dbus_message_iter_next (&struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &flags);
+
+ g_file_attribute_info_list_add (list, name, type, flags);
+ }
+ }
+ }
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ return list;
+}
+
+void
+_g_dbus_append_attribute_info_list (DBusMessageIter *iter,
+ GFileAttributeInfoList *list)
+{
+ DBusMessageIter array_iter, struct_iter;
+ int i;
+ dbus_uint32_t dbus_type, dbus_flags;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; i < list->n_infos; i++)
+ {
+ if (!dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING, &list->infos[i].name))
+ _g_dbus_oom ();
+
+ dbus_type = list->infos[i].type;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_UINT32, &dbus_type))
+ _g_dbus_oom ();
+
+ dbus_flags = list->infos[i].flags;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_UINT32, &dbus_flags))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (iter, &array_iter))
+ _g_dbus_oom ();
+}
diff --git a/trunk/common/gvfsdaemonprotocol.h b/trunk/common/gvfsdaemonprotocol.h
new file mode 100644
index 00000000..dedf86ba
--- /dev/null
+++ b/trunk/common/gvfsdaemonprotocol.h
@@ -0,0 +1,194 @@
+#ifndef __G_VFS_DAEMON_PROTOCOL_H__
+#define __G_VFS_DAEMON_PROTOCOL_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* The well known name of the main daemon */
+#define G_VFS_DBUS_DAEMON_NAME "org.gtk.vfs.Daemon"
+
+/* The mount tracking interface in the main daemon */
+#define G_VFS_DBUS_MOUNTTRACKER_INTERFACE "org.gtk.vfs.MountTracker"
+#define G_VFS_DBUS_MOUNTTRACKER_PATH "/org/gtk/vfs/mounttracker"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT "lookupMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH "lookupMountByFusePath"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION "mountLocation"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS "listMounts"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT "registerMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_UNREGISTER_MOUNT "unregisterMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES "listMountTypes"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO "listMountableInfo"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE "registerFuse"
+#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED "mounted"
+#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED "unmounted"
+
+/* Each mount (there might be several in a daemon) implements one of these interfaces
+ for standard i/o operations */
+#define G_VFS_DBUS_MOUNT_INTERFACE "org.gtk.vfs.Mount"
+#define G_VFS_DBUS_MOUNT_OP_UNMOUNT "Unmount"
+#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ "OpenForRead"
+#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE "OpenForWrite"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_INFO "QueryInfo"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO "QueryFilesystemInfo"
+#define G_VFS_DBUS_MOUNT_OP_ENUMERATE "Enumerate"
+#define G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR "CreateDirectoryMonitor"
+#define G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR "CreateFileMonitor"
+#define G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE "MountMountable"
+#define G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE "UnountMountable"
+#define G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE "EjectMountable"
+#define G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME "SetDisplayName"
+#define G_VFS_DBUS_MOUNT_OP_DELETE "Delete"
+#define G_VFS_DBUS_MOUNT_OP_TRASH "Trash"
+#define G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY "MakeDirectory"
+#define G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK "MakeSymbolicLink"
+#define G_VFS_DBUS_MOUNT_OP_COPY "Copy"
+#define G_VFS_DBUS_MOUNT_OP_MOVE "Move"
+#define G_VFS_DBUS_MOUNT_OP_PUSH "Push"
+#define G_VFS_DBUS_MOUNT_OP_PULL "Pull"
+#define G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE "SetAttribute"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES "QuerySettableAttributes"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES "QueryWritableNamespaces"
+#define G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ "OpenIconForRead"
+
+/* Progress callback interface for copy and move */
+#define G_VFS_DBUS_PROGRESS_INTERFACE "org.gtk.vfs.Progress"
+#define G_VFS_DBUS_PROGRESS_OP_PROGRESS "Progress"
+
+/* mount daemons that support mounting more mounts implement this,
+ and set the dbus name in the mountable description file */
+#define G_VFS_DBUS_MOUNTABLE_INTERFACE "org.gtk.vfs.Mountable"
+#define G_VFS_DBUS_MOUNTABLE_PATH "/org/gtk/vfs/mountable"
+#define G_VFS_DBUS_MOUNTABLE_OP_MOUNT "mount"
+
+#define G_VFS_DBUS_ERROR_SOCKET_FAILED "org.gtk.vfs.Error.SocketFailed"
+
+/* Each daemon (main and for mounts) implement this. */
+#define G_VFS_DBUS_DAEMON_INTERFACE "org.gtk.vfs.Daemon"
+#define G_VFS_DBUS_DAEMON_PATH "/org/gtk/vfs/Daemon"
+#define G_VFS_DBUS_OP_GET_CONNECTION "GetConnection"
+#define G_VFS_DBUS_OP_CANCEL "Cancel"
+
+/* Used by the dbus-proxying implementation of GMoutOperation */
+#define G_VFS_DBUS_MOUNT_OPERATION_INTERFACE "org.gtk.vfs.MountOperation"
+#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD "askPassword"
+#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION "askQuestion"
+
+/* Implemented by the spawner of a process, the spawned process sends the
+ spawned message (with noreply) when it has spawned and gotten a dbus id */
+#define G_VFS_DBUS_SPAWNER_INTERFACE "org.gtk.vfs.Spawner"
+#define G_VFS_DBUS_OP_SPAWNED "spawned"
+
+/* Implemented by client side for a file enumerator */
+#define G_VFS_DBUS_ENUMERATOR_INTERFACE "org.gtk.vfs.Enumerator"
+#define G_VFS_DBUS_ENUMERATOR_OP_DONE "Done"
+#define G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO "GotInfo"
+
+#define G_VFS_DBUS_MONITOR_INTERFACE "org.gtk.vfs.Monitor"
+#define G_VFS_DBUS_MONITOR_OP_SUBSCRIBE "Subscribe"
+#define G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE "Unsubscribe"
+
+#define G_VFS_DBUS_MONITOR_CLIENT_INTERFACE "org.gtk.vfs.MonitorClient"
+#define G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED "Changed"
+
+
+/* Mounts time out in 10 minutes, since they can be slow, with auth, etc */
+#define G_VFS_DBUS_MOUNT_TIMEOUT_MSECS (1000*60*10)
+/* Normal ops are faster, one minute timeout */
+#define G_VFS_DBUS_TIMEOUT_MSECS (1000*60)
+
+typedef struct {
+ guint32 command;
+ guint32 seq_nr;
+ guint32 arg1;
+ guint32 arg2;
+ guint32 data_len;
+} GVfsDaemonSocketProtocolRequest;
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE sizeof(GVfsDaemonSocketProtocolRequest)
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ 0
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE 1
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE 2
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL 3
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET 4
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END 5
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_QUERY_INFO 6
+
+/*
+read, readahead reply:
+type, seek_generation, size, data
+
+seek reply:
+type, pos (64),
+
+error:
+type, code, size, data (size bytes, 2 strings: domain, message)
+
+info:
+type, 0, size, data
+
+*/
+
+typedef struct {
+ guint32 type;
+ guint32 seq_nr;
+ guint32 arg1;
+ guint32 arg2;
+} GVfsDaemonSocketProtocolReply;
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE 16
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA 0
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR 1
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS 2
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN 3
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED 4
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO 5
+
+#define G_FILE_INFO_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ DBUS_TYPE_STRING_AS_STRING \
+ DBUS_TYPE_VARIANT_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+#define G_FILE_INFO_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_FILE_INFO_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+
+typedef union {
+ gboolean boolean;
+ guint32 uint32;
+ guint64 uint64;
+ gpointer ptr;
+} GDbusAttributeValue;
+
+void _g_dbus_attribute_value_destroy (GFileAttributeType type,
+ GDbusAttributeValue *value);
+gpointer _g_dbus_attribute_as_pointer (GFileAttributeType type,
+ GDbusAttributeValue *value);
+const char*_g_dbus_type_from_file_attribute_type (GFileAttributeType type);
+void _g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p);
+void _g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *file_info);
+gboolean _g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GDbusAttributeValue *value);
+GFileInfo *_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error);
+
+GFileAttributeInfoList *_g_dbus_get_attribute_info_list (DBusMessageIter *iter,
+ GError **error);
+void _g_dbus_append_attribute_info_list (DBusMessageIter *iter,
+ GFileAttributeInfoList *list);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DAEMON_PROTOCOL_H__ */
diff --git a/trunk/common/gvfsdnssdresolver.c b/trunk/common/gvfsdnssdresolver.c
new file mode 100644
index 00000000..77940427
--- /dev/null
+++ b/trunk/common/gvfsdnssdresolver.c
@@ -0,0 +1,1269 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+/*
+ * TODO: - locking
+ * - cancellation
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#include <avahi-common/timeval.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
+
+#include "gvfsdnssdutils.h"
+#include "gvfsdnssdresolver.h"
+
+enum
+{
+ PROP_0,
+ PROP_ENCODED_TRIPLE,
+ PROP_REQUIRED_TXT_KEYS,
+ PROP_SERVICE_NAME,
+ PROP_SERVICE_TYPE,
+ PROP_DOMAIN,
+ PROP_TIMEOUT_MSEC,
+
+ PROP_IS_RESOLVED,
+ PROP_ADDRESS,
+ PROP_PORT,
+ PROP_TXT_RECORDS,
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _GVfsDnsSdResolver
+{
+ GObject parent_instance;
+
+ char *encoded_triple;
+ char *service_name;
+ char *service_type;
+ char *domain;
+ char *required_txt_keys;
+ char **required_txt_keys_broken_out;
+ guint timeout_msec;
+
+ gboolean is_resolved;
+ char *address;
+ guint port;
+ char **txt_records;
+
+ AvahiServiceResolver *avahi_resolver;
+};
+
+
+struct _GVfsDnsSdResolverClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*changed) (GVfsDnsSdResolver *resolver);
+};
+
+G_DEFINE_TYPE (GVfsDnsSdResolver, g_vfs_dns_sd_resolver, G_TYPE_OBJECT);
+
+static gboolean resolver_supports_mdns = FALSE;
+static AvahiClient *global_client = NULL;
+static gboolean avahi_initialized = FALSE;
+static void free_global_avahi_client (void);
+static AvahiClient *get_global_avahi_client (GError **error);
+
+static gboolean ensure_avahi_resolver (GVfsDnsSdResolver *resolver,
+ GError **error);
+
+static void service_resolver_cb (AvahiServiceResolver *resolver,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *a,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void *user_data);
+
+
+
+static GList *resolvers = NULL;
+
+static void
+clear_avahi_data (GVfsDnsSdResolver *resolver);
+
+static void
+remove_client_from_resolver (GVfsDnsSdResolver *resolver)
+{
+ if (resolver->avahi_resolver != NULL)
+ {
+ avahi_service_resolver_free (resolver->avahi_resolver);
+ resolver->avahi_resolver = NULL;
+ }
+
+ clear_avahi_data (resolver);
+}
+
+static void
+add_client_to_resolver (GVfsDnsSdResolver *resolver)
+{
+ ensure_avahi_resolver (resolver, NULL);
+}
+
+/* Callback for state changes on the Client */
+static void
+avahi_client_callback (AvahiClient *client, AvahiClientState state, void *userdata)
+{
+ if (global_client == NULL)
+ global_client = client;
+
+ if (state == AVAHI_CLIENT_FAILURE)
+ {
+ if (avahi_client_errno (client) == AVAHI_ERR_DISCONNECTED)
+ {
+ free_global_avahi_client ();
+
+ /* Attempt to reconnect */
+ get_global_avahi_client (NULL);
+ }
+ }
+ else if (state == AVAHI_CLIENT_S_RUNNING)
+ {
+ /* Start resolving again */
+ g_list_foreach (resolvers, (GFunc) add_client_to_resolver, NULL);
+ }
+}
+
+static void
+free_global_avahi_client (void)
+{
+ /* Remove current resolvers */
+ g_list_foreach (resolvers, (GFunc) remove_client_from_resolver, NULL);
+
+ /* Destroy client */
+ avahi_client_free (global_client);
+ global_client = NULL;
+ avahi_initialized = FALSE;
+}
+
+static AvahiClient *
+get_global_avahi_client (GError **error)
+{
+ static AvahiGLibPoll *glib_poll = NULL;
+ int avahi_error;
+
+ if (!avahi_initialized)
+ {
+ avahi_initialized = TRUE;
+
+ if (glib_poll == NULL)
+ {
+ avahi_set_allocator (avahi_glib_allocator ());
+ glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
+ }
+
+ /* Create a new AvahiClient instance */
+ global_client = avahi_client_new (avahi_glib_poll_get (glib_poll),
+ AVAHI_CLIENT_NO_FAIL,
+ avahi_client_callback,
+ glib_poll,
+ &avahi_error);
+
+ if (global_client == NULL)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Error initializing Avahi: %s"),
+ avahi_strerror (avahi_error));
+ goto out;
+ }
+ }
+
+ out:
+
+ return global_client;
+}
+
+
+static gboolean
+ensure_avahi_resolver (GVfsDnsSdResolver *resolver,
+ GError **error)
+{
+ AvahiClient *avahi_client;
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (resolver->avahi_resolver != NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+
+ avahi_client = get_global_avahi_client (error);
+ if (avahi_client == NULL)
+ goto out;
+
+ resolver->avahi_resolver = avahi_service_resolver_new (avahi_client,
+ AVAHI_IF_UNSPEC,
+ AVAHI_PROTO_UNSPEC,
+ resolver->service_name,
+ resolver->service_type,
+ resolver->domain,
+ AVAHI_PROTO_UNSPEC,
+ 0, /* AvahiLookupFlags */
+ service_resolver_cb,
+ resolver);
+ if (resolver->avahi_resolver == NULL)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Error creating Avahi resolver: %s"),
+ avahi_strerror (avahi_client_errno (avahi_client)));
+ goto out;
+ }
+
+ ret = TRUE;
+
+out:
+ return ret;
+}
+
+static void
+g_vfs_dns_sd_resolver_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsDnsSdResolver *resolver = G_VFS_DNS_SD_RESOLVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_ENCODED_TRIPLE:
+ g_value_set_string (value, resolver->encoded_triple);
+ break;
+
+ case PROP_REQUIRED_TXT_KEYS:
+ g_value_set_string (value, resolver->required_txt_keys);
+ break;
+
+ case PROP_SERVICE_NAME:
+ g_value_set_string (value, resolver->service_name);
+ break;
+
+ case PROP_SERVICE_TYPE:
+ g_value_set_string (value, resolver->service_type);
+ break;
+
+ case PROP_DOMAIN:
+ g_value_set_string (value, resolver->domain);
+ break;
+
+ case PROP_TIMEOUT_MSEC:
+ g_value_set_uint (value, resolver->timeout_msec);
+ break;
+
+ case PROP_IS_RESOLVED:
+ g_value_set_boolean (value, resolver->is_resolved);
+ break;
+
+ case PROP_ADDRESS:
+ g_value_set_string (value, resolver->address);
+ break;
+
+ case PROP_PORT:
+ g_value_set_uint (value, resolver->port);
+ break;
+
+ case PROP_TXT_RECORDS:
+ g_value_set_boxed (value, resolver->txt_records);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_vfs_dns_sd_resolver_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsDnsSdResolver *resolver = G_VFS_DNS_SD_RESOLVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_ENCODED_TRIPLE:
+ resolver->encoded_triple = g_strdup (g_value_get_string (value));
+ break;
+
+ case PROP_REQUIRED_TXT_KEYS:
+ resolver->required_txt_keys = g_strdup (g_value_get_string (value));
+ if (resolver->required_txt_keys != NULL)
+ {
+ /* TODO: maybe support escaping ',' */
+ resolver->required_txt_keys_broken_out = g_strsplit (resolver->required_txt_keys, ",", 0);
+ }
+ break;
+
+ case PROP_SERVICE_NAME:
+ resolver->service_name = g_strdup (g_value_get_string (value));
+ break;
+
+ case PROP_SERVICE_TYPE:
+ resolver->service_type = g_strdup (g_value_get_string (value));
+ break;
+
+ case PROP_DOMAIN:
+ resolver->domain = g_strdup (g_value_get_string (value));
+ break;
+
+ case PROP_TIMEOUT_MSEC:
+ resolver->timeout_msec = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_vfs_dns_sd_resolver_finalize (GObject *object)
+{
+ GVfsDnsSdResolver *resolver;
+
+ resolver = G_VFS_DNS_SD_RESOLVER (object);
+
+ g_free (resolver->encoded_triple);
+ g_free (resolver->service_name);
+ g_free (resolver->service_type);
+ g_free (resolver->domain);
+ g_free (resolver->required_txt_keys);
+ g_strfreev (resolver->required_txt_keys_broken_out);
+
+ g_free (resolver->address);
+ g_strfreev (resolver->txt_records);
+
+ if (resolver->avahi_resolver != NULL)
+ avahi_service_resolver_free (resolver->avahi_resolver);
+
+
+ resolvers = g_list_remove (resolvers, resolver);
+
+ /* free the global avahi client for the last resolver */
+ if (resolvers == NULL)
+ {
+ free_global_avahi_client ();
+ }
+
+ G_OBJECT_CLASS (g_vfs_dns_sd_resolver_parent_class)->finalize (object);
+}
+
+static void
+g_vfs_dns_sd_resolver_constructed (GObject *object)
+{
+ GVfsDnsSdResolver *resolver;
+
+ resolver = G_VFS_DNS_SD_RESOLVER (object);
+
+ if (resolver->encoded_triple != NULL)
+ {
+ GError *error;
+
+ if (resolver->service_name != NULL)
+ {
+ g_warning ("Ignoring service-name since encoded-triple is already set");
+ g_free (resolver->service_name);
+ resolver->service_name = NULL;
+ }
+
+ if (resolver->service_type != NULL)
+ {
+ g_warning ("Ignoring service-type since encoded-triple is already set");
+ g_free (resolver->service_type);
+ resolver->service_type = NULL;
+ }
+
+ if (resolver->domain != NULL)
+ {
+ g_warning ("Ignoring domain since encoded-triple is already set");
+ g_free (resolver->domain);
+ resolver->domain = NULL;
+ }
+
+
+ error = NULL;
+ if (!g_vfs_decode_dns_sd_triple (resolver->encoded_triple,
+ &(resolver->service_name),
+ &(resolver->service_type),
+ &(resolver->domain),
+ &error))
+ {
+ /* GObject construction can't fail. So whine if the triple isn't valid. */
+ g_warning ("Malformed construction data passed: %s", error->message);
+ g_error_free (error);
+
+ g_free (resolver->encoded_triple);
+ g_free (resolver->service_name);
+ g_free (resolver->service_type);
+ g_free (resolver->domain);
+ resolver->encoded_triple = NULL;
+ resolver->service_name = NULL;
+ resolver->service_type = NULL;
+ resolver->domain = NULL;
+ goto out;
+ }
+ }
+
+ /* Always set encoded triple to what we encode; this is because we can decode
+ * an encoded triple that isn't 100% properly URI encoded, e.g.
+ *
+ * "davidz's public files on quad.fubar.dk._webdav._tcp.local"
+ *
+ * will be properly decoded. But we want to return a properly URI encoded triple
+ *
+ * "davidz%27s%20public%20files%20on%20quad%2efubar%2edk._webdav._tcp.local"
+ *
+ * for e.g. setting the GMountSpec. This is useful because the use can
+ * put the former into the pathbar in a file manager and then it will
+ * be properly rewritten on mount.
+ */
+ g_free (resolver->encoded_triple);
+ resolver->encoded_triple = g_vfs_encode_dns_sd_triple (resolver->service_name,
+ resolver->service_type,
+ resolver->domain);
+
+ /* start resolving immediately */
+ ensure_avahi_resolver (resolver, NULL);
+
+ resolvers = g_list_prepend (resolvers, resolver);
+
+ out:
+
+ if (G_OBJECT_CLASS (g_vfs_dns_sd_resolver_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (g_vfs_dns_sd_resolver_parent_class)->constructed (object);
+}
+
+static void
+g_vfs_dns_sd_resolver_class_init (GVfsDnsSdResolverClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ resolver_supports_mdns = (avahi_nss_support () > 0);
+
+ gobject_class->get_property = g_vfs_dns_sd_resolver_get_property;
+ gobject_class->set_property = g_vfs_dns_sd_resolver_set_property;
+ gobject_class->finalize = g_vfs_dns_sd_resolver_finalize;
+ gobject_class->constructed = g_vfs_dns_sd_resolver_constructed;
+
+ /**
+ * GVfsDnsSdResolver::changed:
+ * @resolver: The resolver emitting the signal.
+ *
+ * Emitted when resolved data changes.
+ */
+ signals[CHANGED] = g_signal_new ("changed",
+ G_VFS_TYPE_DNS_SD_RESOLVER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsDnsSdResolverClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+
+ /**
+ * GVfsDnsSdResolver:encoded-triple:
+ *
+ * The encoded DNS-SD triple for the resolver.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ENCODED_TRIPLE,
+ g_param_spec_string ("encoded-triple",
+ "Encoded triple",
+ "Encoded triple",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:required-txt-keys:
+ *
+ * A comma separated list of keys that must appear in the TXT
+ * records in order to consider the service being resolved.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_REQUIRED_TXT_KEYS,
+ g_param_spec_string ("required-txt-keys",
+ "Required TXT keys",
+ "Required TXT keys",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:service-name:
+ *
+ * The name of the service for the resolver.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_SERVICE_NAME,
+ g_param_spec_string ("service-name",
+ "Service Name",
+ "Service Name",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:service-type:
+ *
+ * The type of the service for the resolver.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_SERVICE_TYPE,
+ g_param_spec_string ("service-type",
+ "Service Type",
+ "Service Type",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:domain:
+ *
+ * The domain for the resolver.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DOMAIN,
+ g_param_spec_string ("domain",
+ "Domain",
+ "Domain",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:timeout-msec:
+ *
+ * Timeout in milliseconds to use when resolving.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_TIMEOUT_MSEC,
+ g_param_spec_uint ("timeout-msec",
+ "Timeout in milliseconds",
+ "Timeout in milliseconds",
+ 0,
+ G_MAXUINT,
+ 5000,
+ G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:is-resolved:
+ *
+ * Whether the service is resolved.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_IS_RESOLVED,
+ g_param_spec_boolean ("is-resolved",
+ "Is resolved",
+ "Is resolved",
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:address:
+ *
+ * The resolved address.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DOMAIN,
+ g_param_spec_string ("address",
+ "Address",
+ "Address",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:port:
+ *
+ * The resolved port.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_PORT,
+ g_param_spec_uint ("port",
+ "Port",
+ "Port",
+ 0,
+ 65536,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsDnsSdResolver:txt-records:
+ *
+ * The resolved TXT records.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_TXT_RECORDS,
+ g_param_spec_boxed ("txt-records",
+ "TXT Records",
+ "TXT Records",
+ G_TYPE_STRV,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+}
+
+static void
+g_vfs_dns_sd_resolver_init (GVfsDnsSdResolver *resolver)
+{
+}
+
+gboolean
+g_vfs_dns_sd_resolver_is_resolved (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), FALSE);
+ return resolver->is_resolved;
+}
+
+const gchar *
+g_vfs_dns_sd_resolver_get_encoded_triple (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return resolver->encoded_triple;
+}
+
+const gchar *
+g_vfs_dns_sd_resolver_get_required_txt_keys (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return resolver->required_txt_keys;
+}
+
+const gchar *
+g_vfs_dns_sd_resolver_get_service_name (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return resolver->service_name;
+}
+
+const gchar *
+g_vfs_dns_sd_resolver_get_service_type (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return resolver->service_type;
+}
+
+const gchar *
+g_vfs_dns_sd_resolver_get_domain (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return resolver->domain;
+}
+
+gchar *
+g_vfs_dns_sd_resolver_get_address (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return g_strdup (resolver->address);
+}
+
+guint
+g_vfs_dns_sd_resolver_get_port (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), (guint) -1);
+ return resolver->port;
+}
+
+gchar **
+g_vfs_dns_sd_resolver_get_txt_records (GVfsDnsSdResolver *resolver)
+{
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ return g_strdupv (resolver->txt_records);
+}
+
+gchar *
+g_vfs_dns_sd_resolver_lookup_txt_record (GVfsDnsSdResolver *resolver,
+ const gchar *key)
+{
+ gint n;
+ gchar *result;
+ gsize key_len;
+
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+
+ result = NULL;
+
+
+ if (resolver->txt_records == NULL)
+ goto out;
+
+ key_len = strlen (key);
+
+ for (n = 0; resolver->txt_records[n] != NULL; n++)
+ {
+ const gchar *s = resolver->txt_records[n];
+ const gchar *p;
+
+ p = strchr (s, '=');
+ if (p != NULL && (p - s) == key_len)
+ {
+ if (g_ascii_strncasecmp (s,
+ key,
+ p - s) == 0)
+ {
+ result = g_strdup (p + 1);
+ goto out;
+ }
+ }
+ }
+
+ out:
+ return result;
+}
+
+GVfsDnsSdResolver *
+g_vfs_dns_sd_resolver_new_for_encoded_triple (const gchar *encoded_triple,
+ const gchar *required_txt_keys)
+
+{
+ g_return_val_if_fail (encoded_triple != NULL, NULL);
+
+ return G_VFS_DNS_SD_RESOLVER (g_object_new (G_VFS_TYPE_DNS_SD_RESOLVER,
+ "encoded-triple", encoded_triple,
+ "required-txt-keys", required_txt_keys,
+ NULL));
+}
+
+GVfsDnsSdResolver *
+g_vfs_dns_sd_resolver_new_for_service (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain,
+ const gchar *required_txt_keys)
+{
+ g_return_val_if_fail (service_name != NULL, NULL);
+ g_return_val_if_fail (service_type != NULL, NULL);
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ return G_VFS_DNS_SD_RESOLVER (g_object_new (G_VFS_TYPE_DNS_SD_RESOLVER,
+ "service-name", service_name,
+ "service-type", service_type,
+ "domain", domain,
+ "required-txt-keys", required_txt_keys,
+ NULL));
+}
+
+static int
+safe_strcmp (const char *a, const char *b)
+{
+ if (a == NULL)
+ a = "";
+ if (b == NULL)
+ b = "";
+ return strcmp (a, b);
+}
+
+static gboolean
+strv_equal (char **a, char **b)
+{
+ static char *dummy[1] = {NULL};
+ int n;
+ gboolean ret;
+
+ if (a == NULL)
+ a = dummy;
+ if (b == NULL)
+ b = dummy;
+
+ ret = FALSE;
+
+ if (g_strv_length (a) != g_strv_length (b))
+ goto out;
+
+ for (n = 0; a[n] != NULL && b[n] != NULL; n++)
+ {
+ if (strcmp (a[n], b[n]) != 0)
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+
+}
+
+static gboolean
+has_required_txt_keys (GVfsDnsSdResolver *resolver)
+{
+ gboolean ret;
+ int n;
+ char *value;
+
+ ret = FALSE;
+
+ if (resolver->required_txt_keys_broken_out != NULL)
+ {
+ for (n = 0; resolver->required_txt_keys_broken_out[n] != NULL; n++)
+ {
+ value = g_vfs_dns_sd_resolver_lookup_txt_record (resolver,
+ resolver->required_txt_keys_broken_out[n]);
+ if (value == NULL)
+ {
+ /* key is missing */
+ goto out;
+ }
+ g_free (value);
+ }
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static void
+set_avahi_data (GVfsDnsSdResolver *resolver,
+ const char *host_name,
+ AvahiProtocol protocol,
+ const AvahiAddress *a,
+ uint16_t port,
+ AvahiStringList *txt)
+{
+ char *address;
+ gboolean changed;
+ AvahiStringList *l;
+ GPtrArray *p;
+ char **txt_records;
+ gboolean is_resolved;
+
+ changed = FALSE;
+
+ if (resolver_supports_mdns)
+ {
+ address = g_strdup (host_name);
+ }
+ else
+ {
+ char aa[128];
+
+ avahi_address_snprint (aa, sizeof(aa), a);
+ if (protocol == AVAHI_PROTO_INET6)
+ {
+ /* an ipv6 address, follow RFC 2732 */
+ address = g_strdup_printf ("[%s]", aa);
+ }
+ else
+ {
+ address = g_strdup (aa);
+ }
+ }
+
+ if (safe_strcmp (resolver->address, address) != 0)
+ {
+ g_free (resolver->address);
+ resolver->address = g_strdup (address);
+ g_object_notify (G_OBJECT (resolver), "address");
+ changed = TRUE;
+ }
+
+ g_free (address);
+
+ if (resolver->port != port)
+ {
+ resolver->port = port;
+ g_object_notify (G_OBJECT (resolver), "port");
+ changed = TRUE;
+ }
+
+ p = g_ptr_array_new ();
+ for (l = txt; l != NULL; l = avahi_string_list_get_next (l))
+ {
+ g_ptr_array_add (p, g_strdup ((const char *) l->text));
+ }
+ g_ptr_array_add (p, NULL);
+ txt_records = (char **) g_ptr_array_free (p, FALSE);
+
+ if (strv_equal (resolver->txt_records, txt_records))
+ {
+ g_strfreev (txt_records);
+ }
+ else
+ {
+ g_strfreev (resolver->txt_records);
+ resolver->txt_records = txt_records;
+ g_object_notify (G_OBJECT (resolver), "txt-records");
+ changed = TRUE;
+ }
+
+ is_resolved = has_required_txt_keys (resolver);
+
+ if (is_resolved != resolver->is_resolved)
+ {
+ resolver->is_resolved = is_resolved;
+ g_object_notify (G_OBJECT (resolver), "is-resolved");
+ changed = TRUE;
+ }
+
+ if (changed)
+ g_signal_emit (resolver, signals[CHANGED], 0);
+}
+
+static void
+clear_avahi_data (GVfsDnsSdResolver *resolver)
+{
+ gboolean changed;
+
+ changed = FALSE;
+
+ if (resolver->is_resolved)
+ {
+ resolver->is_resolved = FALSE;
+ g_object_notify (G_OBJECT (resolver), "is-resolved");
+ changed = TRUE;
+ }
+
+ if (resolver->address != NULL)
+ {
+ g_free (resolver->address);
+ resolver->address = NULL;
+ g_object_notify (G_OBJECT (resolver), "address");
+ changed = TRUE;
+ }
+
+ if (resolver->port != 0)
+ {
+ resolver->port = 0;
+ g_object_notify (G_OBJECT (resolver), "port");
+ changed = TRUE;
+ }
+
+ if (resolver->txt_records != NULL)
+ {
+ resolver->txt_records = NULL;
+ g_object_notify (G_OBJECT (resolver), "txt-records");
+ changed = TRUE;
+ }
+
+ if (changed)
+ g_signal_emit (resolver, signals[CHANGED], 0);
+}
+
+static void
+service_resolver_cb (AvahiServiceResolver *avahi_resolver,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *a,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void *user_data)
+{
+ GVfsDnsSdResolver *resolver = G_VFS_DNS_SD_RESOLVER (user_data);
+
+ switch (event)
+ {
+ case AVAHI_RESOLVER_FOUND:
+ set_avahi_data (resolver,
+ host_name,
+ protocol,
+ a,
+ port,
+ txt);
+ break;
+
+ case AVAHI_RESOLVER_FAILURE:
+ clear_avahi_data (resolver);
+ break;
+ }
+}
+
+
+typedef struct
+{
+ GVfsDnsSdResolver *resolver;
+ GSimpleAsyncResult *simple;
+ guint timeout_id;
+} ResolveData;
+
+static void service_resolver_changed (GVfsDnsSdResolver *resolver, ResolveData *data);
+
+static void
+resolve_data_free (ResolveData *data)
+{
+ if (data->timeout_id > 0)
+ g_source_remove (data->timeout_id);
+ g_signal_handlers_disconnect_by_func (data->resolver, service_resolver_changed, data);
+ g_object_unref (data->simple);
+ g_free (data);
+}
+
+static void
+service_resolver_changed (GVfsDnsSdResolver *resolver,
+ ResolveData *data)
+{
+ if (resolver->is_resolved)
+ {
+ g_simple_async_result_set_op_res_gboolean (data->simple, TRUE);
+ g_simple_async_result_complete (data->simple);
+ resolve_data_free (data);
+ }
+ else
+ {
+ if (data->resolver->address != NULL)
+ {
+ /* keep going until timeout if we're missing TXT records */
+ }
+ else
+ {
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ /* Translators:
+ * - the first %s refers to the service type
+ * - the second %s refers to the service name
+ * - the third %s refers to the domain
+ */
+ _("Error resolving \"%s\" service \"%s\" on domain \"%s\""),
+ data->resolver->service_type,
+ data->resolver->service_name,
+ data->resolver->domain);
+ g_simple_async_result_complete (data->simple);
+ resolve_data_free (data);
+ }
+ }
+}
+
+static gboolean
+service_resolver_timed_out (ResolveData *data)
+{
+
+ if (data->resolver->address != NULL)
+ {
+ /* special case if one of the required TXT records are missing */
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ /* Translators:
+ * - the first %s refers to the service type
+ * - the second %s refers to the service name
+ * - the third %s refers to the domain
+ * - the fourth %s refers to the required TXT keys
+ */
+ _("Error resolving \"%s\" service \"%s\" on domain \"%s\". "
+ "One or more TXT records are missing. Keys required: \"%s\"."),
+ data->resolver->service_type,
+ data->resolver->service_name,
+ data->resolver->domain,
+ data->resolver->required_txt_keys);
+ }
+ else
+ {
+ g_simple_async_result_set_error (data->simple,
+ G_IO_ERROR,
+ G_IO_ERROR_TIMED_OUT,
+ /* Translators:
+ * - the first %s refers to the service type
+ * - the second %s refers to the service name
+ * - the third %s refers to the domain
+ */
+ _("Timed out resolving \"%s\" service \"%s\" on domain \"%s\""),
+ data->resolver->service_type,
+ data->resolver->service_name,
+ data->resolver->domain);
+ }
+
+ g_simple_async_result_complete (data->simple);
+ data->timeout_id = 0;
+ resolve_data_free (data);
+ return FALSE;
+}
+
+gboolean
+g_vfs_dns_sd_resolver_resolve_finish (GVfsDnsSdResolver *resolver,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), FALSE);
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_vfs_dns_sd_resolver_resolve);
+ g_simple_async_result_propagate_error (simple, error);
+
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+void
+g_vfs_dns_sd_resolver_resolve (GVfsDnsSdResolver *resolver,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ResolveData *data;
+ GSimpleAsyncResult *simple;
+ GError *error;
+
+ g_return_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver));
+
+ simple = g_simple_async_result_new (G_OBJECT (resolver),
+ callback,
+ user_data,
+ g_vfs_dns_sd_resolver_resolve);
+
+
+ if (resolver->is_resolved)
+ {
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+
+ error = NULL;
+ if (!ensure_avahi_resolver (resolver, &error))
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ goto out;
+ }
+
+ data = g_new0 (ResolveData, 1);
+ data->resolver = resolver;
+ data->simple = simple;
+ data->timeout_id = g_timeout_add (resolver->timeout_msec,
+ (GSourceFunc) service_resolver_timed_out,
+ data);
+
+ g_signal_connect (resolver,
+ "changed",
+ (GCallback) service_resolver_changed,
+ data);
+
+ out:
+ ;
+}
+
+
+typedef struct
+{
+ GMainLoop *loop;
+ GError *error;
+ gboolean ret;
+} ResolveDataSync;
+
+static void
+resolve_sync_cb (GVfsDnsSdResolver *resolver,
+ GAsyncResult *res,
+ ResolveDataSync *data)
+{
+ data->ret = g_vfs_dns_sd_resolver_resolve_finish (resolver,
+ res,
+ &(data->error));
+ g_main_loop_quit (data->loop);
+}
+
+
+gboolean
+g_vfs_dns_sd_resolver_resolve_sync (GVfsDnsSdResolver *resolver,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ResolveDataSync *data;
+ gboolean ret;
+
+ g_return_val_if_fail (G_VFS_IS_DNS_SD_RESOLVER (resolver), FALSE);
+
+ data = g_new0 (ResolveDataSync, 1);
+ data->loop = g_main_loop_new (NULL, FALSE);
+
+ g_vfs_dns_sd_resolver_resolve (resolver,
+ cancellable,
+ (GAsyncReadyCallback) resolve_sync_cb,
+ data);
+
+ g_main_loop_run (data->loop);
+
+ ret = data->ret;
+ if (data->error != NULL)
+ g_propagate_error (error, data->error);
+
+ g_main_loop_unref (data->loop);
+ g_free (data);
+
+ return ret;
+}
diff --git a/trunk/common/gvfsdnssdresolver.h b/trunk/common/gvfsdnssdresolver.h
new file mode 100644
index 00000000..a694ff93
--- /dev/null
+++ b/trunk/common/gvfsdnssdresolver.h
@@ -0,0 +1,80 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_DNS_SD_RESOLVER_H__
+#define __G_VFS_DNS_SD_RESOLVER_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_DNS_SD_RESOLVER (g_vfs_dns_sd_resolver_get_type ())
+#define G_VFS_DNS_SD_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_DNS_SD_RESOLVER, GVfsDnsSdResolver))
+#define G_VFS_DNS_SD_RESOLVER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_DNS_SD_RESOLVER, GVfsDnsSdResolverClass))
+#define G_VFS_IS_DNS_SD_RESOLVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_DNS_SD_RESOLVER))
+#define G_VFS_IS_DNS_SD_RESOLVER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_DNS_SD_RESOLVER))
+#define G_VFS_DNS_SD_RESOLVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_DNS_SD_RESOLVER, GVfsDnsSdResolverClass))
+
+/**
+ * GVfsDnsSdResolver:
+ *
+ * Resolves DNS-SD triples.
+ */
+typedef struct _GVfsDnsSdResolver GVfsDnsSdResolver;
+typedef struct _GVfsDnsSdResolverClass GVfsDnsSdResolverClass;
+
+GType g_vfs_dns_sd_resolver_get_type (void) G_GNUC_CONST;
+GVfsDnsSdResolver *g_vfs_dns_sd_resolver_new_for_encoded_triple (const gchar *encoded_triple,
+ const gchar *required_txt_keys);
+GVfsDnsSdResolver *g_vfs_dns_sd_resolver_new_for_service (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain,
+ const gchar *required_txt_keys);
+const gchar *g_vfs_dns_sd_resolver_get_encoded_triple (GVfsDnsSdResolver *resolver);
+const gchar *g_vfs_dns_sd_resolver_get_service_name (GVfsDnsSdResolver *resolver);
+const gchar *g_vfs_dns_sd_resolver_get_service_type (GVfsDnsSdResolver *resolver);
+const gchar *g_vfs_dns_sd_resolver_get_domain (GVfsDnsSdResolver *resolver);
+const gchar *g_vfs_dns_sd_resolver_get_required_txt_keys (GVfsDnsSdResolver *resolver);
+
+void g_vfs_dns_sd_resolver_resolve (GVfsDnsSdResolver *resolver,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_vfs_dns_sd_resolver_resolve_finish (GVfsDnsSdResolver *resolver,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean g_vfs_dns_sd_resolver_resolve_sync (GVfsDnsSdResolver *resolver,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean g_vfs_dns_sd_resolver_is_resolved (GVfsDnsSdResolver *resolver);
+gchar *g_vfs_dns_sd_resolver_get_address (GVfsDnsSdResolver *resolver);
+guint g_vfs_dns_sd_resolver_get_port (GVfsDnsSdResolver *resolver);
+gchar **g_vfs_dns_sd_resolver_get_txt_records (GVfsDnsSdResolver *resolver);
+gchar *g_vfs_dns_sd_resolver_lookup_txt_record (GVfsDnsSdResolver *resolver,
+ const gchar *key);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DNS_SD_RESOLVER_H__ */
diff --git a/trunk/common/gvfsdnssdutils.c b/trunk/common/gvfsdnssdutils.c
new file mode 100644
index 00000000..f6592e1a
--- /dev/null
+++ b/trunk/common/gvfsdnssdutils.c
@@ -0,0 +1,323 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#include <avahi-common/timeval.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
+
+#include "gvfsdnssdutils.h"
+
+static gchar *
+escape_service_name (const gchar *service_name)
+{
+ GString *s;
+ char *res;
+ const gchar *p;
+
+ g_return_val_if_fail (service_name != NULL, NULL);
+
+ s = g_string_new (NULL);
+
+ p = service_name;
+ while (*p != '\0')
+ {
+ if (*p == '\\')
+ g_string_append (s, "\\\\");
+ else if (*p == '.')
+ g_string_append (s, "\\.");
+ else if (*p == '/')
+ g_string_append (s, "\\s");
+ else
+ g_string_append_c (s, *p);
+ p++;
+ }
+
+ res = g_uri_escape_string (s->str, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
+ g_string_free (s, TRUE);
+ return res;
+}
+
+static gchar *
+escape_service_name2 (const gchar *service_name)
+{
+ GString *s;
+ const gchar *p;
+
+ g_return_val_if_fail (service_name != NULL, NULL);
+
+ s = g_string_new (NULL);
+
+ p = service_name;
+ while (*p != '\0')
+ {
+ if (*p == '.')
+ g_string_append (s, "%2e");
+ else
+ g_string_append_c (s, *p);
+ p++;
+ }
+
+ return g_string_free (s, FALSE);
+}
+
+/**
+ * g_vfs_get_dns_sd_uri_for_triple:
+ * @service_name: DNS-SD service name.
+ * @service_type: DNS-SD service type.
+ * @domain: DNS-SD domain.
+ *
+ * Creates an URI for a file on the GVfs <literal>dns-sd</literal>
+ * virtual file system that provides live data for resolving the given
+ * DNS-SD service.
+ *
+ * The URI is of the form
+ * <literal>dns-sd://domain/service_name.service_type<literal> with
+ * suitable encoding added.
+ *
+ * Note that there may not exist a file at the returned URI, the
+ * resource providing the DNS-SD service will have to be available for
+ * the file to exist.
+ *
+ * Returns: An URI. Free with g_free().
+ **/
+gchar *
+g_vfs_get_dns_sd_uri_for_triple (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain)
+{
+ gchar *escaped_service_name;
+ gchar *ret;
+
+ g_return_val_if_fail (service_name != NULL, NULL);
+ g_return_val_if_fail (service_type != NULL, NULL);
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ escaped_service_name = escape_service_name (service_name);
+
+ ret = g_strdup_printf ("dns-sd://%s/%s.%s",
+ domain,
+ escaped_service_name,
+ service_type);
+ g_free (escaped_service_name);
+
+ return ret;
+}
+
+/**
+ * g_vfs_encode_dns_sd_triple:
+ * @service_name: DNS-SD service name.
+ * @service_type: DNS-SD service type.
+ * @domain: DNS-SD domain.
+ *
+ * Creates an encoded triple representing a DNS-SD service. The triple
+ * will be of the form
+ * <literal>service_name.service_type.domain</literal> with suitable
+ * encoding.
+ *
+ * Use g_vfs_decode_dns_sd_triple() to decode the returned string.
+ *
+ * Returns: A string representing the triple, free with g_free().
+ **/
+gchar *
+g_vfs_encode_dns_sd_triple (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain)
+{
+ char *dot_escaped_service_name;
+ char *escaped_service_name;
+ char *escaped_service_type;
+ char *escaped_domain;
+ char *s;
+
+ escaped_service_name = g_uri_escape_string (service_name, NULL, FALSE);
+ dot_escaped_service_name = escape_service_name2 (escaped_service_name);
+ escaped_service_type = g_uri_escape_string (service_type, NULL, FALSE);
+ escaped_domain = g_uri_escape_string (domain, NULL, FALSE);
+ s = g_strdup_printf ("%s.%s.%s",
+ dot_escaped_service_name,
+ escaped_service_type,
+ escaped_domain);
+ g_free (dot_escaped_service_name);
+ g_free (escaped_service_name);
+ g_free (escaped_service_type);
+ g_free (escaped_domain);
+ return s;
+}
+
+/**
+ * g_vfs_decode_dns_sd_triple:
+ * @encoded_triple: A string obtained from g_vfs_encode_dns_sd_triple().
+ * @out_service_name: %NULL or return location for the service name.
+ * @out_service_type: %NULL or return location for the service type.
+ * @out_domain: %NULL or return location for the domain.
+ * @error: Return location for error or %NULL.
+ *
+ * Constructs a DNS-SD triple by decoding a string generated from
+ * g_vfs_encode_dns_sd_triple(). This can fail if @encoded_triple is
+ * malformed.
+ *
+ * Returns: %TRUE unless @error is set.
+ **/
+gboolean
+g_vfs_decode_dns_sd_triple (const gchar *encoded_triple,
+ gchar **out_service_name,
+ gchar **out_service_type,
+ gchar **out_domain,
+ GError **error)
+{
+ gboolean ret;
+ int n;
+ int m;
+ int service_type_pos;
+ char *escaped_service_name;
+ char *escaped_service_type;
+ char *escaped_domain;
+
+ g_return_val_if_fail (encoded_triple != NULL, FALSE);
+
+
+ escaped_service_name = NULL;
+ escaped_service_type = NULL;
+ escaped_domain = NULL;
+ ret = FALSE;
+
+ if (out_service_name != NULL)
+ *out_service_name = NULL;
+
+ if (out_service_type != NULL)
+ *out_service_type = NULL;
+
+ if (out_domain != NULL)
+ *out_domain = NULL;
+
+ /* Find first '.' followed by an underscore. */
+ for (n = 0; encoded_triple[n] != '\0'; n++)
+ {
+ if (encoded_triple[n] == '.')
+ {
+ if (encoded_triple[n + 1] == '_')
+ break;
+ }
+ }
+ if (encoded_triple[n] == '\0')
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed dns-sd encoded_triple '%s'"),
+ encoded_triple);
+ goto out;
+ }
+
+ escaped_service_name = g_strndup (encoded_triple, n);
+ if (escaped_service_name == NULL)
+ goto out;
+
+ if (out_service_name != NULL)
+ *out_service_name = g_uri_unescape_string (escaped_service_name, NULL);
+
+ /* skip dot between service name and service type */
+ n += 1;
+
+ service_type_pos = n;
+
+ /* skip next two dots */
+ for (m = 0; m < 2; m++)
+ {
+ for (; encoded_triple[n] != '\0'; n++)
+ {
+ if (encoded_triple[n] == '.')
+ break;
+ }
+ if (encoded_triple[n] == '\0')
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed dns-sd encoded_triple '%s'"),
+ encoded_triple);
+ goto out;
+ }
+ n++;
+ }
+
+ escaped_service_type = g_strndup (encoded_triple + service_type_pos, n - service_type_pos - 1);
+ if (out_service_type != NULL)
+ *out_service_type = g_uri_unescape_string (escaped_service_type, NULL);
+
+ /* the domain is the rest */
+ if (encoded_triple[n] == '\0')
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed dns-sd encoded_triple '%s'"),
+ encoded_triple);
+ goto out;
+ }
+
+ escaped_domain = g_strdup (encoded_triple + n);
+ if (out_domain != NULL)
+ *out_domain = g_uri_unescape_string (escaped_domain, NULL);
+
+ ret = TRUE;
+
+ out:
+ g_free (escaped_service_name);
+ g_free (escaped_service_type);
+ g_free (escaped_domain);
+ return ret;
+}
+
+gchar *
+g_vfs_normalize_encoded_dns_sd_triple (const gchar *encoded_triple)
+{
+ char *service_name;
+ char *service_type;
+ char *domain;
+ char *ret;
+
+ ret = NULL;
+
+ if (!g_vfs_decode_dns_sd_triple (encoded_triple,
+ &service_name,
+ &service_type,
+ &domain,
+ NULL))
+ goto out;
+
+ ret = g_vfs_encode_dns_sd_triple (service_name, service_type, domain);
+ g_free (service_name);
+ g_free (service_type);
+ g_free (domain);
+
+ out:
+ return ret;
+}
+
diff --git a/trunk/common/gvfsdnssdutils.h b/trunk/common/gvfsdnssdutils.h
new file mode 100644
index 00000000..21fe8a54
--- /dev/null
+++ b/trunk/common/gvfsdnssdutils.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_DNS_SD_UTILS_H__
+#define __G_VFS_DNS_SD_UTILS_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gchar *g_vfs_encode_dns_sd_triple (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain);
+
+gchar *g_vfs_normalize_encoded_dns_sd_triple (const gchar *encoded_triple);
+
+gboolean
+g_vfs_decode_dns_sd_triple (const gchar *encoded_triple,
+ gchar **out_service_name,
+ gchar **out_service_type,
+ gchar **out_domain,
+ GError **error);
+
+gchar *
+g_vfs_get_dns_sd_uri_for_triple (const gchar *service_name,
+ const gchar *service_type,
+ const gchar *domain);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DNS_SD_UTILS_H__ */
diff --git a/trunk/common/gvfsfileinfo.c b/trunk/common/gvfsfileinfo.c
new file mode 100644
index 00000000..df563cc7
--- /dev/null
+++ b/trunk/common/gvfsfileinfo.c
@@ -0,0 +1,278 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <string.h>
+#include "gvfsfileinfo.h"
+
+static void
+put_string (GDataOutputStream *out,
+ const char *str)
+{
+ gsize len;
+
+ len = strlen (str);
+ if (len > G_MAXUINT16)
+ {
+ g_warning ("GFileInfo string to large, (%d bytes)\n", (int)len);
+ len = 0;
+ str = "";
+ }
+
+ g_data_output_stream_put_uint16 (out, len,
+ NULL, NULL);
+ g_data_output_stream_put_string (out, str, NULL, NULL);
+}
+
+static char *
+read_string (GDataInputStream *in)
+{
+ gsize len;
+ char *str;
+
+ len = g_data_input_stream_read_uint16 (in, NULL, NULL);
+ str = g_malloc (len + 1);
+ g_input_stream_read_all (G_INPUT_STREAM (in), str, len, &len, NULL, NULL);
+ str[len] = 0;
+ return str;
+}
+
+char *
+gvfs_file_info_marshal (GFileInfo *info,
+ gsize *size)
+{
+ GOutputStream *memstream;
+ GDataOutputStream *out;
+ GFileAttributeType type;
+ GFileAttributeStatus status;
+ GObject *obj;
+ char **attrs, *attr;
+ char *data;
+ int i;
+
+ memstream = g_memory_output_stream_new (NULL, 0, g_realloc, NULL);
+
+ out = g_data_output_stream_new (memstream);
+ g_object_unref (memstream);
+
+ attrs = g_file_info_list_attributes (info, NULL);
+
+ g_data_output_stream_put_uint32 (out,
+ g_strv_length (attrs),
+ NULL, NULL);
+
+ for (i = 0; attrs[i] != NULL; i++)
+ {
+ attr = attrs[i];
+
+ type = g_file_info_get_attribute_type (info, attr);
+ status = g_file_info_get_attribute_status (info, attr);
+
+ put_string (out, attr);
+ g_data_output_stream_put_byte (out, type,
+ NULL, NULL);
+ g_data_output_stream_put_byte (out, status,
+ NULL, NULL);
+
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ put_string (out, g_file_info_get_attribute_string (info, attr));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ put_string (out, g_file_info_get_attribute_byte_string (info, attr));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
+ g_data_output_stream_put_byte (out,
+ g_file_info_get_attribute_boolean (info, attr),
+ NULL, NULL);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ g_data_output_stream_put_uint32 (out,
+ g_file_info_get_attribute_uint32 (info, attr),
+ NULL, NULL);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ g_data_output_stream_put_int32 (out,
+ g_file_info_get_attribute_int32 (info, attr),
+ NULL, NULL);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ g_data_output_stream_put_uint64 (out,
+ g_file_info_get_attribute_uint64 (info, attr),
+ NULL, NULL);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ g_data_output_stream_put_int64 (out,
+ g_file_info_get_attribute_int64 (info, attr),
+ NULL, NULL);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ obj = g_file_info_get_attribute_object (info, attr);
+ if (obj == NULL)
+ {
+ g_data_output_stream_put_byte (out, 0,
+ NULL, NULL);
+ }
+ else if (G_IS_ICON (obj))
+ {
+ char *icon_str;
+
+ icon_str = g_icon_to_string (G_ICON (obj));
+ g_data_output_stream_put_byte (out, 1,
+ NULL, NULL);
+ put_string (out, icon_str);
+ g_free (icon_str);
+ }
+ else
+ {
+ g_warning ("Unsupported GFileInfo object type %s\n",
+ g_type_name_from_instance ((GTypeInstance *)obj));
+ g_data_output_stream_put_byte (out, 0,
+ NULL, NULL);
+ }
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INVALID:
+ default:
+ break;
+ }
+ }
+
+ data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (memstream));
+ *size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (memstream));
+ g_object_unref (out);
+ g_strfreev (attrs);
+ return data;
+}
+
+GFileInfo *
+gvfs_file_info_demarshal (char *data,
+ gsize size)
+{
+ guint32 num_attrs, i;
+ GInputStream *memstream;
+ GDataInputStream *in;
+ GFileInfo *info;
+ char *attr, *str;
+ GFileAttributeType type;
+ GFileAttributeStatus status;
+ GObject *obj;
+ int objtype;
+
+ memstream = g_memory_input_stream_new_from_data (data, size, NULL);
+ in = g_data_input_stream_new (memstream);
+ g_object_unref (memstream);
+
+ info = g_file_info_new ();
+ num_attrs = g_data_input_stream_read_uint32 (in, NULL, NULL);
+
+ for (i = 0; i < num_attrs; i++)
+ {
+ attr = read_string (in);
+ type = g_data_input_stream_read_byte (in, NULL, NULL);
+ status = g_data_input_stream_read_byte (in, NULL, NULL);
+
+ /* TODO: There is no way to set the status. This is required for
+ g_file_set_attributes_from_info() */
+
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ str = read_string (in);
+ g_file_info_set_attribute_string (info, attr, str);
+ g_free (str);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ str = read_string (in);
+ g_file_info_set_attribute_byte_string (info, attr, str);
+ g_free (str);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
+ g_file_info_set_attribute_boolean (info, attr,
+ g_data_input_stream_read_byte (in,
+ NULL,
+ NULL));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ g_file_info_set_attribute_uint32 (info, attr,
+ g_data_input_stream_read_uint32 (in,
+ NULL,
+ NULL));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ g_file_info_set_attribute_int32 (info, attr,
+ g_data_input_stream_read_int32 (in,
+ NULL,
+ NULL));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ g_file_info_set_attribute_uint64 (info, attr,
+ g_data_input_stream_read_uint64 (in,
+ NULL,
+ NULL));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ g_file_info_set_attribute_int64 (info, attr,
+ g_data_input_stream_read_int64 (in,
+ NULL,
+ NULL));
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ objtype = g_data_input_stream_read_byte (in, NULL, NULL);
+ obj = NULL;
+
+ if (objtype == 1)
+ {
+ char *icon_str;
+
+ icon_str = read_string (in);
+ obj = (GObject *)g_icon_new_for_string (icon_str, NULL);
+ g_free (icon_str);
+ }
+ else
+ {
+ g_warning ("Unsupported GFileInfo object type %d\n", objtype);
+ g_free (attr);
+ goto out;
+ }
+ g_file_info_set_attribute_object (info, attr, obj);
+ if (obj)
+ g_object_unref (obj);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INVALID:
+ default:
+ g_warning ("Unsupported GFileInfo attribute type %d\n", type);
+ g_free (attr);
+ goto out;
+ break;
+ }
+ g_free (attr);
+ }
+
+ out:
+ g_object_unref (in);
+ return info;
+}
+
+
diff --git a/trunk/common/gvfsfileinfo.h b/trunk/common/gvfsfileinfo.h
new file mode 100644
index 00000000..970f9e4f
--- /dev/null
+++ b/trunk/common/gvfsfileinfo.h
@@ -0,0 +1,37 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_FILE_INFO_H__
+#define __G_VFS_FILE_INFO_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+char * gvfs_file_info_marshal (GFileInfo *info,
+ gsize *size);
+GFileInfo *gvfs_file_info_demarshal (char *data,
+ gsize size);
+
+G_END_DECLS
+
+#endif /* __G_VFS_FILE_INFO_H__ */
diff --git a/trunk/common/gvfsicon.c b/trunk/common/gvfsicon.c
new file mode 100644
index 00000000..62a29f1e
--- /dev/null
+++ b/trunk/common/gvfsicon.c
@@ -0,0 +1,282 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "gvfsicon.h"
+
+static void g_vfs_icon_icon_iface_init (GIconIface *iface);
+
+/* Because of the way dependencies are currently set up, the
+ * GLoadableIcon interface is in client/gvfsiconloadable.c and is
+ * added in g_io_module_load() in client/gdaemonvfs.c.
+ */
+
+enum
+{
+ PROP_0,
+ PROP_MOUNT_SPEC,
+ PROP_ICON_ID
+};
+
+G_DEFINE_TYPE_EXTENDED (GVfsIcon,
+ g_vfs_icon,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
+ g_vfs_icon_icon_iface_init))
+
+static void
+g_vfs_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsIcon *icon = G_VFS_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOUNT_SPEC:
+ g_value_set_boxed (value, icon->mount_spec);
+ break;
+
+ case PROP_ICON_ID:
+ g_value_set_string (value, icon->icon_id);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_vfs_icon_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsIcon *icon = G_VFS_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_MOUNT_SPEC:
+ icon->mount_spec = g_mount_spec_ref (g_value_get_boxed (value));
+ break;
+
+ case PROP_ICON_ID:
+ icon->icon_id = g_strdup (g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_vfs_icon_finalize (GObject *object)
+{
+ GVfsIcon *vfs_icon;
+
+ vfs_icon = G_VFS_ICON (object);
+
+ if (vfs_icon->mount_spec != NULL)
+ g_mount_spec_unref (vfs_icon->mount_spec);
+ g_free (vfs_icon->icon_id);
+
+ G_OBJECT_CLASS (g_vfs_icon_parent_class)->finalize (object);
+}
+
+static void
+g_vfs_icon_class_init (GVfsIconClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = g_vfs_icon_get_property;
+ gobject_class->set_property = g_vfs_icon_set_property;
+ gobject_class->finalize = g_vfs_icon_finalize;
+
+ /**
+ * GVfsIcon:mount-spec:
+ *
+ * The mount spec.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_MOUNT_SPEC,
+ g_param_spec_boxed ("mount-spec",
+ "Mount Spec",
+ "Mount Spec",
+ G_TYPE_MOUNT_SPEC,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * GVfsIcon:icon-id:
+ *
+ * The id of the icon.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ICON_ID,
+ g_param_spec_string ("icon-id",
+ "Icon identifier",
+ "Icon identifier",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+}
+
+static void
+g_vfs_icon_init (GVfsIcon *file)
+{
+}
+
+GMountSpec *
+g_vfs_icon_get_mount_spec (GVfsIcon *vfs_icon)
+{
+ g_return_val_if_fail (G_VFS_IS_ICON (vfs_icon), NULL);
+ return g_mount_spec_ref (vfs_icon->mount_spec);
+}
+
+const gchar *
+g_vfs_icon_get_icon_id (GVfsIcon *vfs_icon)
+{
+ g_return_val_if_fail (G_VFS_IS_ICON (vfs_icon), NULL);
+ return vfs_icon->icon_id;
+}
+
+
+GIcon *
+g_vfs_icon_new (GMountSpec *mount_spec,
+ const gchar *icon_id)
+{
+ return G_ICON (g_object_new (G_VFS_TYPE_ICON,
+ "mount-spec", mount_spec,
+ "icon-id", icon_id,
+ NULL));
+}
+
+static guint
+g_vfs_icon_hash (GIcon *icon)
+{
+ GVfsIcon *vfs_icon = G_VFS_ICON (icon);
+
+ return g_mount_spec_hash (vfs_icon->mount_spec) ^ g_str_hash (vfs_icon->icon_id);
+}
+
+static int
+safe_strcmp (const char *a,
+ const char *b)
+{
+ if (a == NULL)
+ a = "";
+ if (b == NULL)
+ b = "";
+
+ return strcmp (a, b);
+}
+
+static gboolean
+g_vfs_icon_equal (GIcon *icon1,
+ GIcon *icon2)
+{
+ GVfsIcon *vfs1 = G_VFS_ICON (icon1);
+ GVfsIcon *vfs2 = G_VFS_ICON (icon2);
+
+ return g_mount_spec_equal (vfs1->mount_spec, vfs2->mount_spec) &&
+ (safe_strcmp (vfs1->icon_id, vfs2->icon_id) == 0);
+}
+
+static gboolean
+g_vfs_icon_to_tokens (GIcon *icon,
+ GPtrArray *tokens,
+ gint *out_version)
+{
+ GVfsIcon *vfs_icon = G_VFS_ICON (icon);
+ char *s;
+
+ g_return_val_if_fail (out_version != NULL, FALSE);
+
+ *out_version = 0;
+
+ s = g_mount_spec_to_string (vfs_icon->mount_spec);
+ g_ptr_array_add (tokens, s);
+ g_ptr_array_add (tokens, g_strdup (vfs_icon->icon_id));
+
+ return TRUE;
+}
+
+static GIcon *
+g_vfs_icon_from_tokens (gchar **tokens,
+ gint num_tokens,
+ gint version,
+ GError **error)
+{
+ GMountSpec *mount_spec;
+ GIcon *icon;
+
+ icon = NULL;
+
+ if (version != 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Can't handle version %d of GVfsIcon encoding"),
+ version);
+ goto out;
+ }
+
+ if (num_tokens != 2)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed input data for GVfsIcon"));
+ goto out;
+ }
+
+ mount_spec = g_mount_spec_new_from_string (tokens[0], error);
+ if (mount_spec == NULL)
+ goto out;
+
+ icon = g_vfs_icon_new (mount_spec, tokens[1]);
+ g_mount_spec_unref (mount_spec);
+
+ out:
+ return icon;
+}
+
+static void
+g_vfs_icon_icon_iface_init (GIconIface *iface)
+{
+ iface->hash = g_vfs_icon_hash;
+ iface->equal = g_vfs_icon_equal;
+ iface->to_tokens = g_vfs_icon_to_tokens;
+ iface->from_tokens = g_vfs_icon_from_tokens;
+}
diff --git a/trunk/common/gvfsicon.h b/trunk/common/gvfsicon.h
new file mode 100644
index 00000000..b32c2ba4
--- /dev/null
+++ b/trunk/common/gvfsicon.h
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_ICON_H__
+#define __G_VFS_ICON_H__
+
+#include <gio/gio.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_ICON (g_vfs_icon_get_type ())
+#define G_VFS_ICON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_ICON, GVfsIcon))
+#define G_VFS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_ICON, GVfsIconClass))
+#define G_VFS_IS_ICON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_ICON))
+#define G_VFS_IS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_ICON))
+#define G_VFS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_ICON, GVfsIconClass))
+
+/**
+ * GVfsIcon:
+ *
+ * An object for referencing icons originating from a #GVfsBackend
+ */
+typedef struct _GVfsIcon GVfsIcon;
+typedef struct _GVfsIconClass GVfsIconClass;
+
+struct _GVfsIcon
+{
+ GObject parent_instance;
+
+ GMountSpec *mount_spec;
+ char *icon_id;
+};
+
+struct _GVfsIconClass
+{
+ GObjectClass parent_class;
+};
+
+GType g_vfs_icon_get_type (void) G_GNUC_CONST;
+
+GIcon *g_vfs_icon_new (GMountSpec *mount_spec,
+ const gchar *icon_id);
+
+GMountSpec *g_vfs_icon_get_mount_spec (GVfsIcon *vfs_icon);
+const gchar *g_vfs_icon_get_icon_id (GVfsIcon *vfs_icon);
+
+G_END_DECLS
+
+#endif /* __G_VFS_ICON_H__ */
diff --git a/trunk/common/gvfsmountinfo.c b/trunk/common/gvfsmountinfo.c
new file mode 100644
index 00000000..327929f5
--- /dev/null
+++ b/trunk/common/gvfsmountinfo.c
@@ -0,0 +1,737 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "gvfsmountinfo.h"
+
+#define VOLUME_INFO_GROUP "Volume Info"
+
+static GFile *
+_g_find_file_insensitive_finish (GFile *parent,
+ GAsyncResult *result,
+ GError **error);
+
+static void
+_g_find_file_insensitive_async (GFile *parent,
+ const gchar *name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+static void
+on_icon_file_located (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GFile *icon_file;
+ GError *error;
+
+ error = NULL;
+ icon_file = _g_find_file_insensitive_finish (G_FILE (source_object),
+ res,
+ &error);
+ if (icon_file != NULL)
+ {
+ g_simple_async_result_set_op_res_gpointer (simple, g_file_icon_new (icon_file), NULL);
+ g_object_unref (icon_file);
+ }
+ else
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+on_autorun_loaded (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GFile *autorun_file;
+ gchar *content;
+ gchar *relative_icon_path;
+ gsize content_length;
+ GError *error;
+
+ relative_icon_path = NULL;
+
+ autorun_file = G_FILE (source_object);
+
+ error = NULL;
+ if (g_file_load_contents_finish (autorun_file,
+ res,
+ &content,
+ &content_length,
+ NULL,
+ &error))
+ {
+ /* Scan through for an "icon=" line. Can't use GKeyFile,
+ * because .inf files aren't always valid key files
+ **/
+ GRegex *icon_regex;
+ GMatchInfo *match_info;
+
+ /* [^,] is because sometimes the icon= line
+ * has a comma at the end
+ **/
+ icon_regex = g_regex_new ("icon=([^,\\r\\n]+)",
+ G_REGEX_CASELESS, 0, NULL);
+ g_regex_match (icon_regex, content, 0,
+ &match_info);
+
+ /* Even if there are multiple matches, pick only the
+ * first.
+ **/
+ if (g_match_info_matches (match_info))
+ {
+ gchar *chr;
+ gchar *word = g_match_info_fetch (match_info, 1);
+
+ /* Replace '\' with '/' */
+ while ((chr = strchr (word, '\\')) != NULL)
+ *chr = '/';
+
+ /* If the file name's not valid UTF-8,
+ * don't even try to load it
+ **/
+ if (g_utf8_validate (word, -1, NULL))
+ {
+ relative_icon_path = word;
+ }
+ else
+ {
+ /* TODO: mark for translation. Strictly, this isn't very important; this string
+ * will never be displayed since all current users of g_vfs_mount_info_query_autorun_info()
+ * passes NULL for the GError**.
+ */
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Icon name is not valid UTF-8");
+ g_free (word);
+ }
+ }
+
+ g_match_info_free (match_info);
+
+ g_regex_unref (icon_regex);
+ g_free (content);
+ }
+
+ /* some autorun.in points to the .exe file for the icon; make sure we avoid using that */
+ if (relative_icon_path != NULL)
+ {
+ if (!g_str_has_suffix (relative_icon_path, ".exe"))
+ {
+ GFile *root;
+
+ root = g_file_get_parent (autorun_file);
+
+ _g_find_file_insensitive_async (root,
+ relative_icon_path,
+ NULL,
+ on_icon_file_located,
+ simple);
+
+ g_object_unref (root);
+ }
+ else
+ {
+ /* TODO: mark for translation. Strictly, this isn't very important; this string
+ * will never be displayed since all current users of g_vfs_mount_info_query_autorun_info()
+ * passes NULL for the GError**.
+ */
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Icon is an .exe file");
+ }
+ }
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ }
+
+ g_free (relative_icon_path);
+}
+
+static void
+on_autorun_located (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GFile *autorun_path;
+ GError *error;
+
+ error = NULL;
+ autorun_path = _g_find_file_insensitive_finish (G_FILE (source_object),
+ res,
+ &error);
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ }
+ else
+ {
+ g_file_load_contents_async (autorun_path,
+ g_object_get_data (G_OBJECT (simple), "cancellable"),
+ on_autorun_loaded,
+ simple);
+ g_object_unref (autorun_path);
+ }
+}
+
+void
+g_vfs_mount_info_query_autorun_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (directory),
+ callback,
+ user_data,
+ g_vfs_mount_info_query_autorun_info);
+
+ if (cancellable != NULL)
+ g_object_set_data_full (G_OBJECT (simple), "cancellable", g_object_ref (cancellable), g_object_unref);
+
+ _g_find_file_insensitive_async (directory,
+ "autorun.inf",
+ cancellable,
+ on_autorun_located,
+ simple);
+}
+
+GIcon *
+g_vfs_mount_info_query_autorun_info_finish (GFile *directory,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GIcon *ret;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_vfs_mount_info_query_autorun_info);
+
+ ret = NULL;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ goto out;
+
+ ret = g_simple_async_result_get_op_res_gpointer (simple);
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_xdg_volume_info_loaded (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GFile *xdg_volume_info_file;
+ gchar *content;
+ gsize content_length;
+ GError *error;
+ GKeyFile *key_file;
+ gchar *name;
+ gchar *icon_name;
+ gchar *icon_file;
+ GIcon *icon;
+
+ content = NULL;
+ key_file = NULL;
+ name = NULL;
+ icon_name = NULL;
+ icon_file = NULL;
+
+ xdg_volume_info_file = G_FILE (source_object);
+
+ error = NULL;
+ if (g_file_load_contents_finish (xdg_volume_info_file,
+ res,
+ &content,
+ &content_length,
+ NULL,
+ &error))
+ {
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_data (key_file,
+ content,
+ content_length,
+ G_KEY_FILE_NONE,
+ &error))
+ goto out;
+
+
+ name = g_key_file_get_locale_string (key_file,
+ VOLUME_INFO_GROUP,
+ "Name",
+ NULL,
+ NULL);
+
+ icon_name = g_key_file_get_string (key_file,
+ VOLUME_INFO_GROUP,
+ "Icon",
+ NULL);
+
+ icon_file = g_key_file_get_string (key_file,
+ VOLUME_INFO_GROUP,
+ "IconFile",
+ NULL);
+
+ icon = NULL;
+
+ if (icon_file != NULL)
+ {
+ GFile *dir, *f;
+
+ dir = g_file_get_parent (xdg_volume_info_file);
+ if (dir)
+ {
+ f = g_file_resolve_relative_path (dir, icon_file);
+ if (f)
+ {
+ icon = g_file_icon_new (f);
+ g_object_unref (f);
+ }
+
+ g_object_unref (dir);
+ }
+ }
+
+ if (icon == NULL && icon_name != NULL)
+ {
+ icon = g_themed_icon_new (icon_name);
+ g_themed_icon_append_name (G_THEMED_ICON (icon), "drive-removable-media");
+ g_themed_icon_append_name (G_THEMED_ICON (icon), "drive-removable");
+ g_themed_icon_append_name (G_THEMED_ICON (icon), "drive");
+ }
+
+ g_simple_async_result_set_op_res_gpointer (simple, icon, NULL);
+ g_object_set_data_full (G_OBJECT (simple), "name", name, g_free);
+ name = NULL; /* steals name */
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ }
+
+ out:
+
+ if (key_file != NULL)
+ g_key_file_free (key_file);
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ }
+
+ g_free (name);
+ g_free (icon_name);
+ g_free (icon_file);
+ g_free (content);
+}
+
+void
+g_vfs_mount_info_query_xdg_volume_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ GFile *file;
+
+ simple = g_simple_async_result_new (G_OBJECT (directory),
+ callback,
+ user_data,
+ g_vfs_mount_info_query_xdg_volume_info);
+
+ file = g_file_resolve_relative_path (directory, ".xdg-volume-info");
+ g_file_load_contents_async (file,
+ cancellable,
+ on_xdg_volume_info_loaded,
+ simple);
+ g_object_unref (file);
+}
+
+GIcon *g_vfs_mount_info_query_xdg_volume_info_finish (GFile *directory,
+ GAsyncResult *res,
+ gchar **out_name,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GIcon *ret;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_vfs_mount_info_query_xdg_volume_info);
+
+ ret = NULL;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ goto out;
+
+ ret = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (out_name != NULL)
+ *out_name = g_strdup (g_object_get_data (G_OBJECT (simple), "name"));
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#define INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK 100
+
+static void
+enumerated_children_callback (GObject *source_object, GAsyncResult *res,
+ gpointer user_data);
+
+static void
+more_files_callback (GObject *source_object, GAsyncResult *res,
+ gpointer user_data);
+
+static void
+find_file_insensitive_exists_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+typedef struct _InsensitiveFileSearchData
+{
+ GFile *root;
+ gchar *original_path;
+ gchar **split_path;
+ gint index;
+ GFileEnumerator *enumerator;
+ GFile *current_file;
+
+ GCancellable *cancellable;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} InsensitiveFileSearchData;
+
+static void
+_g_find_file_insensitive_async (GFile *parent,
+ const gchar *name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ InsensitiveFileSearchData *data;
+ GFile *direct_file = g_file_get_child (parent, name);
+
+ data = g_new0 (InsensitiveFileSearchData, 1);
+ data->cancellable = cancellable;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->root = g_object_ref (parent);
+ data->original_path = g_strdup (name);
+
+ g_file_query_info_async (direct_file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+ cancellable,
+ find_file_insensitive_exists_callback, data);
+
+
+}
+
+static void
+clear_find_file_insensitive_state (InsensitiveFileSearchData *data)
+{
+ if (data->root)
+ g_object_unref (data->root);
+ g_free (data->original_path);
+ if (data->split_path)
+ g_strfreev (data->split_path);
+ if (data->enumerator)
+ g_object_unref (data->enumerator);
+ if (data->current_file)
+ g_object_unref (data->current_file);
+ g_free (data);
+}
+
+static void
+find_file_insensitive_exists_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GFileInfo *info;
+ InsensitiveFileSearchData *data = (InsensitiveFileSearchData *) (user_data);
+
+ /* The file exists and can be found with the given path, no need to search. */
+ if ((info = g_file_query_info_finish (G_FILE (source_object), res, NULL)))
+ {
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (data->root),
+ data->callback,
+ data->user_data,
+ _g_find_file_insensitive_async);
+
+ g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (source_object), g_object_unref);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ clear_find_file_insensitive_state (data);
+ }
+
+ else
+ {
+ data->split_path = g_strsplit (data->original_path, G_DIR_SEPARATOR_S, -1);
+ data->index = 0;
+ data->enumerator = NULL;
+ data->current_file = g_object_ref (data->root);
+
+ /* Skip any empty components due to multiple slashes */
+ while (data->split_path[data->index] != NULL &&
+ *data->split_path[data->index] == 0)
+ data->index++;
+
+ g_file_enumerate_children_async (data->current_file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ 0, G_PRIORITY_DEFAULT,
+ data->cancellable,
+ enumerated_children_callback, data);
+ }
+
+ g_object_unref (source_object);
+}
+
+static void
+enumerated_children_callback (GObject *source_object, GAsyncResult *res,
+ gpointer user_data)
+{
+ GFileEnumerator *enumerator;
+ InsensitiveFileSearchData *data = (InsensitiveFileSearchData *) (user_data);
+
+ enumerator = g_file_enumerate_children_finish (G_FILE (source_object),
+ res, NULL);
+
+ if (enumerator == NULL)
+ {
+ GSimpleAsyncResult *simple;
+ GFile *file;
+
+ simple = g_simple_async_result_new (G_OBJECT (data->root),
+ data->callback,
+ data->user_data,
+ _g_find_file_insensitive_async);
+
+ file = g_file_get_child (data->root, data->original_path);
+
+ g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (file), g_object_unref);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ clear_find_file_insensitive_state (data);
+ return;
+ }
+
+ data->enumerator = enumerator;
+ g_file_enumerator_next_files_async (enumerator,
+ INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK,
+ G_PRIORITY_DEFAULT,
+ data->cancellable,
+ more_files_callback,
+ data);
+}
+
+static void
+more_files_callback (GObject *source_object, GAsyncResult *res,
+ gpointer user_data)
+{
+ InsensitiveFileSearchData *data = (InsensitiveFileSearchData *) (user_data);
+ GList *files, *l;
+ gchar *filename = NULL, *component, *case_folded_name,
+ *name_collation_key;
+ gboolean end_of_files, is_utf8;
+
+ files = g_file_enumerator_next_files_finish (data->enumerator,
+ res, NULL);
+
+ end_of_files = files == NULL;
+
+ component = data->split_path[data->index];
+ g_return_if_fail (component != NULL);
+
+ is_utf8 = (g_utf8_validate (component, -1, NULL));
+ if (is_utf8)
+ {
+ case_folded_name = g_utf8_casefold (component, -1);
+ name_collation_key = g_utf8_collate_key (case_folded_name, -1);
+ g_free (case_folded_name);
+ }
+
+ else
+ {
+ name_collation_key = g_ascii_strdown (component, -1);
+ }
+
+ for (l = files; l != NULL; l = l->next)
+ {
+ GFileInfo *info;
+ const gchar *this_name;
+ gchar *key;
+
+ info = l->data;
+ this_name = g_file_info_get_name (info);
+
+ if (is_utf8 && g_utf8_validate (this_name, -1, NULL))
+ {
+ gchar *case_folded;
+ case_folded = g_utf8_casefold (this_name, -1);
+ key = g_utf8_collate_key (case_folded, -1);
+ g_free (case_folded);
+ }
+ else
+ {
+ key = g_ascii_strdown (this_name, -1);
+ }
+
+ if (strcmp (key, name_collation_key) == 0)
+ filename = g_strdup (this_name);
+ g_free (key);
+
+ if (filename)
+ break;
+ }
+
+ g_list_foreach (files, (GFunc)g_object_unref, NULL);
+ g_list_free (files);
+ g_free (name_collation_key);
+
+ if (filename)
+ {
+ GFile *next_file;
+
+ g_file_enumerator_close_async (data->enumerator,
+ G_PRIORITY_DEFAULT,
+ data->cancellable,
+ NULL, NULL);
+ g_object_unref (data->enumerator);
+ data->enumerator = NULL;
+
+ /* Set the current file and continue searching */
+ next_file = g_file_get_child (data->current_file, filename);
+ g_free (filename);
+ g_object_unref (data->current_file);
+ data->current_file = next_file;
+
+ data->index++;
+ /* Skip any empty components due to multiple slashes */
+ while (data->split_path[data->index] != NULL &&
+ *data->split_path[data->index] == 0)
+ data->index++;
+
+ if (data->split_path[data->index] == NULL)
+ {
+ /* Search is complete, file was found */
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (data->root),
+ data->callback,
+ data->user_data,
+ _g_find_file_insensitive_async);
+
+ g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (data->current_file), g_object_unref);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ clear_find_file_insensitive_state (data);
+ return;
+ }
+
+ /* Continue searching down the tree */
+ g_file_enumerate_children_async (data->current_file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ 0, G_PRIORITY_DEFAULT,
+ data->cancellable,
+ enumerated_children_callback,
+ data);
+ return;
+ }
+
+ if (end_of_files)
+ {
+ /* Could not find the given file, abort the search */
+ GSimpleAsyncResult *simple;
+ GFile *file;
+
+ g_object_unref (data->enumerator);
+ data->enumerator = NULL;
+
+ simple = g_simple_async_result_new (G_OBJECT (data->root),
+ data->callback,
+ data->user_data,
+ _g_find_file_insensitive_async);
+
+ file = g_file_get_child (data->root, data->original_path);
+ g_simple_async_result_set_op_res_gpointer (simple, file, g_object_unref);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ clear_find_file_insensitive_state (data);
+ return;
+ }
+
+ /* Continue enumerating */
+ g_file_enumerator_next_files_async (data->enumerator,
+ INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK,
+ G_PRIORITY_DEFAULT,
+ data->cancellable,
+ more_files_callback,
+ data);
+}
+
+static GFile *
+_g_find_file_insensitive_finish (GFile *parent,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ GFile *file;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ file = G_FILE (g_simple_async_result_get_op_res_gpointer (simple));
+ return g_object_ref (file);
+}
diff --git a/trunk/common/gvfsmountinfo.h b/trunk/common/gvfsmountinfo.h
new file mode 100644
index 00000000..6879f04a
--- /dev/null
+++ b/trunk/common/gvfsmountinfo.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_MOUNT_INFO_H__
+#define __G_VFS_MOUNT_INFO_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+void g_vfs_mount_info_query_autorun_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GIcon *g_vfs_mount_info_query_autorun_info_finish (GFile *directory,
+ GAsyncResult *res,
+ GError **error);
+
+void g_vfs_mount_info_query_xdg_volume_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GIcon *g_vfs_mount_info_query_xdg_volume_info_finish (GFile *directory,
+ GAsyncResult *res,
+ gchar **out_name,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_VFS_MOUNT_INFO_H__ */
diff --git a/trunk/configure.ac b/trunk/configure.ac
new file mode 100644
index 00000000..85628d89
--- /dev/null
+++ b/trunk/configure.ac
@@ -0,0 +1,585 @@
+AC_INIT(client/gdaemonvfs.h)
+
+AM_INIT_AUTOMAKE(gvfs, 1.2.0)
+AM_CONFIG_HEADER(config.h)
+
+AM_SANITY_CHECK
+
+AC_C_CONST
+AC_ISC_POSIX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AM_DISABLE_STATIC
+AM_PROG_LIBTOOL
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+AM_PROG_CC_C_O
+
+
+# Make libtool use --silent when --silent is passed to make
+changequote(,)dnl
+LIBTOOL="${LIBTOOL} \$(shell echo \"\$(MFLAGS)\" | awk '/^[^ ]*s/ { print \"--silent\" }')"
+changequote([,])dnl
+
+AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+
+AH_VERBATIM([_GNU_SOURCE],
+[/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif])
+
+saved_CFLAGS=$CFLAGS
+AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec, struct stat.st_atimensec, struct stat.st_atim.tv_nsec, struct stat.st_ctimensec, struct stat.st_ctim.tv_nsec])
+CFLAGS=$saved_CFLAGS
+
+LIBTOOL_EXPORT_OPTIONS='-export-symbols-regex "^[[^_]].*"'
+AC_SUBST(LIBTOOL_EXPORT_OPTIONS)
+
+GTK_DOC_CHECK
+DISTCHECK_CONFIGURE_FLAGS="--enable-gtk-doc"
+AC_SUBST(DISTCHECK_CONFIGURE_FLAGS)
+
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.19.1 gthread-2.0 gobject-2.0 gmodule-no-export-2.0 gio-unix-2.0 gio-2.0)
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
+
+PKG_CHECK_MODULES(DBUS, dbus-1)
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
+AC_ARG_WITH(dbus_service_dir, [ --with-dbus-service-dir=PATH choose directory for dbus service files, [default=PREFIX/share/dbus-1/services]], with_dbus_service_dir="$withval", with_dbus_service_dir=$datadir/dbus-1/services)
+DBUS_SERVICE_DIR=$with_dbus_service_dir
+AC_SUBST(DBUS_SERVICE_DIR)
+
+dnl **** gio module path handling ****
+giomodulesdir=`pkg-config --variable=giomoduledir gio-2.0`
+AC_SUBST(giomodulesdir)
+
+dnl ****************************
+dnl *** Checks for intltool ***
+dnl ****************************
+
+IT_PROG_INTLTOOL([0.35.0])
+GETTEXT_PACKAGE=gvfs
+
+AC_SUBST([GETTEXT_PACKAGE])
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[The gettext domain name])
+AM_GLIB_GNU_GETTEXT
+
+dnl ****************************
+dnl *** Checks for gettext ***
+dnl ****************************
+
+dnl *** disabled by now, using intltool ***
+dnl *** we'll revert when glib-gettexttize will be able
+dnl *** to manage [enconding: UTF-8] in POTIFILES.in
+
+dnl GETTEXT_PACKAGE=gvfs
+dnl AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [The gettext domain name])
+dnl AC_SUBST(GETTEXT_PACKAGE)
+
+dnl ALL_LINGUAS=""
+
+dnl AM_GLIB_GNU_GETTEXT
+
+dnl LIBS="$LIBS $INTLLIBS"
+
+dnl AM_GLIB_DEFINE_LOCALEDIR(GVFS_LOCALEDIR)
+
+dnl ****************************
+dnl *** Checks for ssh stuff ***
+dnl ****************************
+
+AC_PATH_PROG(SSH_PROGRAM, ssh, "ssh")
+
+dnl ****************************
+dnl *** Checks for pty stuff ***
+dnl ****************************
+
+AC_CHECK_HEADERS(sys/un.h stropts.h termios.h utmp.h sys/uio.h sys/param.h)
+
+# Check for PTY handling functions.
+AC_CHECK_FUNCS(getpt posix_openpt grantpt unlockpt ptsname ptsname_r)
+
+# Pull in the right libraries for various functions which might not be
+# bundled into an exploded libc.
+AC_CHECK_FUNC(socketpair,[have_socketpair=1],AC_CHECK_LIB(socket,socketpair,[have_socketpair=1; LIBS="$LIBS -lsocket"]))
+if test x$have_socketpair = x1 ; then
+ AC_DEFINE(HAVE_SOCKETPAIR,1,[Define if you have the socketpair function.])
+fi
+
+AC_SEARCH_LIBS(login_tty, util, [AC_DEFINE([HAVE_LOGIN_TTY],[],[Whether login_tty is available])])
+
+dnl **************************************************
+dnl *** Check if we should build with http backend ***
+dnl **************************************************
+AC_ARG_ENABLE(http, [ --disable-http build without http/dav backend])
+msg_http=no
+HTTP_CFLAGS=
+HTTP_LIBS=
+
+if test "x$enable_http" != "xno"; then
+ PKG_CHECK_EXISTS(libsoup-gnome-2.4 >= 2.25.1, msg_http=yes)
+
+ if test "x$msg_http" = "xyes"; then
+ PKG_CHECK_MODULES(HTTP, libsoup-gnome-2.4 libxml-2.0)
+ AC_DEFINE(HAVE_HTTP, 1, [Define to 1 if http/dav is going to be built])
+ fi
+fi
+
+AC_SUBST(HTTP_CFLAGS)
+AC_SUBST(HTTP_LIBS)
+AM_CONDITIONAL(HAVE_HTTP, [test "$msg_http" = "yes"])
+
+dnl **************************************************
+dnl *** Check if we should build with DNS-SD backend ***
+dnl **************************************************
+AM_CONDITIONAL(HAVE_AVAHI, false)
+
+AC_ARG_ENABLE(avahi, [ --disable-avahi build without avahi support])
+msg_avahi=no
+if test "x$enable_avahi" != "xno"; then
+ PKG_CHECK_MODULES(AVAHI, avahi-glib >= 0.6 avahi-client >= 0.6,
+ [AM_CONDITIONAL(HAVE_AVAHI, true)
+ AC_DEFINE(HAVE_AVAHI, [], [Set if we can use avahi])]
+ msg_avahi=yes,
+ [AM_CONDITIONAL(HAVE_AVAHI, false)])
+ AC_SUBST(AVAHI_CFLAGS)
+ AC_SUBST(AVAHI_LIBS)
+fi
+
+dnl **********************
+dnl *** Check for FUSE ***
+dnl **********************
+AC_ARG_ENABLE(fuse, [ --disable-fuse build without FUSE support])
+msg_fuse=no
+FUSE_LIBS=
+FUSE_CFLAGS=
+
+if test "x$enable_fuse" != "xno"; then
+ PKG_CHECK_EXISTS(fuse, msg_fuse=yes)
+
+ if test "x$msg_fuse" = "xyes"; then
+ PKG_CHECK_MODULES(FUSE, fuse)
+ AC_DEFINE(HAVE_FUSE, 1, [Define to 1 if FUSE is available])
+ fi
+fi
+
+AC_SUBST(FUSE_LIBS)
+AC_SUBST(FUSE_CFLAGS)
+
+AM_CONDITIONAL(USE_FUSE, [test "$msg_fuse" = "yes"])
+
+dnl **********************
+dnl *** Check for GConf ***
+dnl **********************
+AC_ARG_ENABLE(gconf, [ --disable-gconf build without GConf support])
+msg_gconf=no
+GCONF_LIBS=
+GCONF_CFLAGS=
+
+if test "x$enable_gconf" != "xno"; then
+ PKG_CHECK_EXISTS(gconf-2.0, msg_gconf=yes)
+
+ if test "x$msg_gconf" = "xyes"; then
+ PKG_CHECK_MODULES(GCONF, gconf-2.0)
+ AC_DEFINE(HAVE_GCONF, 1, [Define to 1 if GConf is available])
+ fi
+fi
+
+AC_SUBST(GCONF_LIBS)
+AC_SUBST(GCONF_CFLAGS)
+
+AM_CONDITIONAL(USE_GCONF, [test "$msg_gconf" = "yes"])
+
+dnl **********************
+dnl *** Check for HAL ***
+dnl **********************
+AC_ARG_ENABLE(hal, [ --disable-hal build without HAL support])
+msg_hal=no
+have_hal_fast_init=no
+HAL_LIBS=
+HAL_CFLAGS=
+HAL_REQUIRED=0.5.10
+
+if test "x$enable_hal" != "xno"; then
+ PKG_CHECK_EXISTS([hal >= $HAL_REQUIRED], msg_hal=yes)
+
+ if test "x$msg_hal" = "xyes"; then
+ PKG_CHECK_MODULES([HAL],[hal >= $HAL_REQUIRED])
+ AC_DEFINE(HAVE_HAL, 1, [Define to 1 if HAL is available])
+ save_libs="$LIBS"
+ LIBS="$HAL_LIBS"
+ AC_CHECK_LIB(hal, libhal_get_all_devices_with_properties, have_hal_fast_init=yes)
+ if test "x$have_hal_fast_init" = "xyes"; then
+ AC_DEFINE(HAVE_HAL_FAST_INIT, 1, [Define to 1 if libhal_get_all_devices_with_properties is available])
+ fi
+ LIBS="$save_libs"
+ fi
+fi
+
+AC_SUBST(HAL_LIBS)
+AC_SUBST(HAL_CFLAGS)
+
+AM_CONDITIONAL(USE_HAL, [test "$msg_hal" = "yes"])
+
+dnl **************************************************
+dnl *** Check if we should build with CDDA backend ***
+dnl **************************************************
+AC_ARG_ENABLE(cdda, [ --disable-cdda build without CDDA backend])
+msg_cdda=no
+CDDA_LIBS=
+CDDA_CFLAGS=
+
+if test "x$enable_cdda" != "xno"; then
+ PKG_CHECK_EXISTS(libcdio_paranoia >= 0.78.2 hal >= $HAL_REQUIRED, msg_cdda=yes)
+
+ if test "x$msg_cdda" = "xyes"; then
+ PKG_CHECK_MODULES(CDDA, libcdio_paranoia hal >= $HAL_REQUIRED)
+ AC_DEFINE(HAVE_CDDA, 1, [Define to 1 if CDDA is going to be built])
+ fi
+fi
+
+AC_SUBST(CDDA_LIBS)
+AC_SUBST(CDDA_CFLAGS)
+
+AM_CONDITIONAL(USE_CDDA, [test "$msg_cdda" = "yes"])
+
+dnl *****************************************************
+dnl *** Check if we should build with obexftp backend ***
+dnl *****************************************************
+AC_ARG_ENABLE(obexftp, [ --disable-obexftp build without ObexFTP backend])
+msg_obexftp=no
+OBEXFTP_LIBS=
+OBEXFTP_CFLAGS=
+
+if test "x$enable_obexftp" != "xno" -a "x$msg_hal" = "xyes" ; then
+ PKG_CHECK_EXISTS(dbus-glib-1 bluez >= 4.0, msg_obexftp=yes)
+
+ dnl Make sure we have expat
+ AC_CHECK_LIB(expat, XML_ParserCreate_MM,
+ [ AC_CHECK_HEADERS(expat.h, have_expat=true, have_expat=false) ],
+ have_expat=false)
+
+ if test "x$msg_obexftp" = "xyes" -a "x$have_expat" = "xtrue"; then
+ PKG_CHECK_MODULES(OBEXFTP, dbus-glib-1 bluez >= 4.0)
+ AC_SUBST(OBEXFTP_LIBS)
+ AC_SUBST(OBEXFTP_CFLAGS)
+
+ msg_obexftp=yes
+ AC_DEFINE(HAVE_OBEXFTP, 1, [Define to 1 if ObexFTP is going to be built])
+ XML_CFLAGS=""
+ XML_LIBS="-lexpat"
+ else
+ msg_obexftp=no
+ fi
+fi
+
+AC_SUBST(XML_LIBS)
+AC_SUBST(XML_CFLAGS)
+
+AM_CONDITIONAL(USE_OBEXFTP, [test "$msg_obexftp" = "yes"])
+
+dnl *************************
+dnl *** Check for gphoto2 ***
+dnl *************************
+AC_ARG_ENABLE(gphoto2, [ --disable-gphoto2 build without gphoto2 support])
+msg_gphoto2=no
+GPHOTO2_LIBS=
+GPHOTO2_CFLAGS=
+
+if test "x$enable_gphoto2" != "xno" -a "x$msg_hal" = "xyes" ; then
+ PKG_CHECK_EXISTS(libgphoto2, msg_gphoto2=yes)
+
+ # Need OS tweaks in hal volume monitor backend
+ case "$host" in
+ *-linux*)
+ use_gphoto2=yes
+ ;;
+ *)
+ use_gphoto2=no
+ ;;
+ esac
+
+ if test "x$msg_gphoto2" = "xyes"; then
+ if test "x$use_gphoto2" = "xyes"; then
+ PKG_CHECK_MODULES(GPHOTO2, libgphoto2 >= 2.4.0)
+ AC_DEFINE(HAVE_GPHOTO2, 1, [Define to 1 if gphoto2 is available])
+ else
+ AC_MSG_WARN([Not building with gphoto2 support. Need OS tweaks in hal volume monitor.])
+ msg_gphoto2=no
+ fi
+ fi
+fi
+
+AC_SUBST(GPHOTO2_LIBS)
+AC_SUBST(GPHOTO2_CFLAGS)
+
+AM_CONDITIONAL(USE_GPHOTO2, [test "$msg_gphoto2" = "yes"])
+
+dnl *******************************
+dnl *** Check for GNOME Keyring ***
+dnl *******************************
+AC_ARG_ENABLE(keyring, [ --disable-keyring build without GNOME Keyring support])
+msg_keyring=no
+KEYRING_LIBS=
+KEYRING_CFLAGS=
+
+if test "x$enable_keyring" != "xno"; then
+ PKG_CHECK_EXISTS(gnome-keyring-1, msg_keyring=yes)
+
+ if test "x$msg_keyring" = "xyes"; then
+ PKG_CHECK_MODULES(KEYRING, gnome-keyring-1)
+ AC_DEFINE(HAVE_KEYRING, 1, [Define to 1 if GNOME Keyring is available])
+ fi
+fi
+
+AC_SUBST(KEYRING_LIBS)
+AC_SUBST(KEYRING_CFLAGS)
+
+AM_CONDITIONAL(USE_KEYRING, [test "$msg_keyring" = "yes"])
+
+dnl ==========================================================================
+dnl Samba 3.0
+
+AC_ARG_ENABLE(samba, [ --disable-samba build without samba support])
+msg_samba="no"
+if test "x$enable_samba" != "xno"; then
+ AC_ARG_WITH(samba-includes, [ --with-samba-includes=PREFIX Location of samba includes.],
+ with_samba_includes="$withval", with_samba_includes="/usr/include")
+ have_samba_includes="no"
+ if test "x${with_samba_includes}" != "xno"; then
+ CPPFLAGS_save="$CPPFLAGS"
+
+ CPPFLAGS="$CPPFLAGS -I$with_samba_includes"
+ AC_CHECK_HEADER(libsmbclient.h, [ samba_includes="yes" ])
+ CPPFLAGS="$CPPFLAGS_save"
+
+ if test "x{samba_includes}" != "xno" -a "x${samba_includes}" != "x"; then
+ have_samba_includes="yes"
+ if test "${with_samba_includes}" != "/usr/include" ; then
+ SAMBA_CFLAGS="-I$with_samba_includes"
+ else
+ SAMBA_CFLAGS=""
+ fi
+
+ CPPFLAGS="$CPPFLAGS -I$with_samba_includes"
+ AC_CHECK_MEMBER(SMBCCTX.flags,
+ [AC_DEFINE(HAVE_SAMBA_FLAGS,, [Defined if flags available in SMBCCTXT])],,
+ [#include <libsmbclient.h>])
+ AC_CHECK_MEMBER(SMBCCTX.close,
+ [AC_DEFINE(HAVE_SAMBA_OLD_CLOSE, , [Defined if old close is available in SMBCCTXT])],,
+ [#include <libsmbclient.h>])
+ CPPFLAGS="$CPPFLAGS_save"
+ else
+ SAMBA_CFLAGS=""
+ fi
+ fi
+ AC_ARG_WITH(samba-libs, [ --with-samba-libs=PREFIX Location of Samba libs.],
+ with_samba_libs="$withval", with_samba_libs="/usr/lib")
+ if test "x${with_samba_libs}" != "xno" -a "x${have_samba_includes}" != "xno"; then
+ LDFLAGS_save="$LDFLAGS"
+
+ LDFLAGS="$LDFLAGS -L$with_samba_libs"
+ AC_CHECK_LIB(smbclient, smbc_option_get,samba_libs="yes", samba_libs="no")
+ LDFLAGS="$LDFLAGS_save"
+ if test "x${samba_libs}" != "xno"; then
+ AC_DEFINE(HAVE_SAMBA,, [Define to 1 if you have the samba 3.0 libraries])
+ msg_samba="yes"
+ if test x$with_samba_libs != x/usr/lib; then
+ SAMBA_LIBS="-L$with_samba_libs -lsmbclient"
+ else
+ SAMBA_LIBS="-lsmbclient"
+ fi
+ else
+ AC_CHECK_LIB(smbclient, smbc_new_context,samba_old_libs="yes", samba_old_libs="no")
+ if test "x${samba_old_libs}" != "xno"; then
+ msg_samba="Too old, need at least samba 3.0.22"
+ fi
+ SAMBA_CFLAGS=""
+ SAMBA_LIBS=""
+ fi
+ fi
+ AC_MSG_CHECKING(for Samba 3.0 libraries)
+ AC_MSG_RESULT($msg_samba)
+fi
+AM_CONDITIONAL(HAVE_SAMBA, test "$msg_samba" = "yes")
+AC_SUBST(SAMBA_CFLAGS)
+AC_SUBST(SAMBA_LIBS)
+
+dnl ==========================================================================
+
+dnl ****************************
+dnl *** Check for libarchive ***
+dnl ****************************
+
+AC_ARG_ENABLE(archive, [ --disable-archive build without archive support])
+msg_archive="no"
+if test "x$enable_archive" != "xno"; then
+ AC_ARG_WITH(archive-includes, [ --with-archive-includes=PREFIX Location of archive includes.],
+ with_archive_includes="$withval", with_archive_includes="/usr/include")
+ have_archive_includes="no"
+ if test "x${with_archive_includes}" != "xno"; then
+ CPPFLAGS_save="$CPPFLAGS"
+
+ CPPFLAGS="$CPPFLAGS -I$with_archive_includes"
+ AC_CHECK_HEADER(archive.h, [ archive_includes="yes" ])
+ CPPFLAGS="$CPPFLAGS_save"
+
+ if test "x{archive_includes}" != "xno" -a "x${archive_includes}" != "x"; then
+ have_archive_includes="yes"
+ if test "${with_archive_includes}" != "/usr/include" ; then
+ ARCHIVE_CFLAGS="-I$with_archive_includes"
+ else
+ ARCHIVE_CFLAGS=""
+ fi
+ else
+ ARCHIVE_CFLAGS=""
+ fi
+ fi
+ AC_ARG_WITH(archive-libs, [ --with-archive-libs=PREFIX Location of Archive libs.],
+ with_archive_libs="$withval", with_archive_libs="/usr/lib")
+ if test "x${with_archive_libs}" != "xno" -a "x${have_archive_includes}" != "xno"; then
+ LDFLAGS_save="$LDFLAGS"
+
+ LDFLAGS="$LDFLAGS -L$with_archive_libs"
+ AC_CHECK_LIB(archive, archive_entry_filetype, archive_libs="yes", archive_libs="no")
+ LDFLAGS="$LDFLAGS_save"
+ if test "x${archive_libs}" != "xno"; then
+ AC_DEFINE(HAVE_ARCHIVE,, [Define to 1 if you have the libarchive library])
+ msg_archive="yes"
+ if test x$with_archive_libs != x/usr/lib; then
+ ARCHIVE_LIBS="-L$with_archive_libs -larchive"
+ else
+ ARCHIVE_LIBS="-larchive"
+ fi
+ else
+ AC_CHECK_LIB(archive, archive_entry_filetype, archive_old_libs="yes", archive_old_libs="no")
+ if test "x${archive_old_libs}" != "xno"; then
+ msg_archive="Too old, need at least archive 3.0.22"
+ fi
+ ARCHIVE_CFLAGS=""
+ ARCHIVE_LIBS=""
+ fi
+ fi
+ AC_MSG_CHECKING(for Archive 3.libraries)
+ AC_MSG_RESULT($msg_archive)
+fi
+AM_CONDITIONAL(HAVE_ARCHIVE, test "$msg_archive" = "yes")
+AC_SUBST(ARCHIVE_CFLAGS)
+AC_SUBST(ARCHIVE_LIBS)
+
+dnl Install bash-completion file?
+AC_ARG_ENABLE([bash-completion],
+ AC_HELP_STRING([--disable-bash-completion],
+ [build without bash-completion support]),
+ msg_bash_completion=$enableval,
+ msg_bash_completion=yes)
+if test "x$enable_bash_completion" != "xno"; then
+ msg_bash_completion=yes
+fi
+AM_CONDITIONAL(ENABLE_BASHCOMP, test "$msg_bash_completion" = "yes")
+
+AC_ARG_WITH([bash-completion-dir],
+ AC_HELP_STRING([--with-bash-completion-dir=PATH],
+ [choose directory for bash-completion file (default=SYSCONFDIR/profile.d)]),
+ with_bashcomp_dir=$withval,
+ with_bashcomp_dir=$sysconfdir/profile.d)
+BASHCOMP_DIR=$with_bashcomp_dir
+AC_SUBST(BASHCOMP_DIR)
+
+dnl ==========================================================================
+
+dnl Globally define_GNU_SOURCE and therefore enable the GNU extensions
+AC_DEFINE(_GNU_SOURCE, 1, [Enable GNU Extensions])
+
+dnl ==========================================================================
+
+AC_DEFINE(_FILE_OFFSET_BITS, 64, [Enable LFS])
+
+dnl ==========================================================================
+
+AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
+
+dnl ==========================================================================
+dnl Turn on the additional warnings last, so -Werror doesn't affect other tests.
+
+AC_ARG_ENABLE(more-warnings,
+[ --enable-more-warnings Maximum compiler warnings],
+set_more_warnings="$enableval",[
+if test -f $srcdir/CVSVERSION; then
+ is_cvs_version=true
+ set_more_warnings=yes
+else
+ set_more_warnings=no
+fi
+])
+AC_MSG_CHECKING(for more warnings, including -Werror)
+if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+ AC_MSG_RESULT(yes)
+ CFLAGS="\
+ -Wall \
+ -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
+ -Wnested-externs -Wpointer-arith \
+ -Wcast-align -Wsign-compare \
+ $CFLAGS"
+
+ for option in -Wno-strict-aliasing -Wno-sign-compare; do
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $option"
+ AC_MSG_CHECKING([whether gcc understands $option])
+ AC_TRY_COMPILE([], [],
+ has_option=yes,
+ has_option=no,)
+ if test $has_option = no; then
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ AC_MSG_RESULT($has_option)
+ unset has_option
+ unset SAVE_CFLAGS
+ done
+ unset option
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_OUTPUT([
+Makefile
+common/Makefile
+client/Makefile
+daemon/trashlib/Makefile
+daemon/Makefile
+monitor/Makefile
+monitor/proxy/Makefile
+monitor/hal/Makefile
+monitor/gphoto2/Makefile
+gconf/Makefile
+programs/Makefile
+test/Makefile
+po/Makefile.in
+])
+
+echo
+echo "gvfs configuration summary:"
+echo "
+ gio module directory : $giomodulesdir
+
+ FTP/HTTP/WebDAV support $msg_http
+ ObexFTP support $msg_obexftp
+ Samba support: $msg_samba
+ FUSE support: $msg_fuse
+ CDDA support: $msg_cdda
+ Gphoto2 support: $msg_gphoto2
+ archive support: $msg_archive
+ GConf support: $msg_gconf
+ DNS-SD support: $msg_avahi
+ Use HAL for volume monitor: $msg_hal (with fast init path: $have_hal_fast_init)
+ GNOME Keyring support: $msg_keyring
+ Bash-completion support: $msg_bash_completion
+"
diff --git a/trunk/daemon/.gitignore b/trunk/daemon/.gitignore
new file mode 100644
index 00000000..2331dfbd
--- /dev/null
+++ b/trunk/daemon/.gitignore
@@ -0,0 +1,16 @@
+*~
+*.o
+*.lo
+*.la
+.deps
+.libs
+Makefile
+Makefile.in
+gvfs-daemon
+gvfs-daemon-smb
+gvfs-daemon-ftp
+gvfs-daemon-sftp
+gvfs-daemon-smb-browse
+gvfs-daemon-test
+*.service
+*.mount
diff --git a/trunk/daemon/Makefile.am b/trunk/daemon/Makefile.am
new file mode 100644
index 00000000..58a32a5c
--- /dev/null
+++ b/trunk/daemon/Makefile.am
@@ -0,0 +1,414 @@
+SUBDIRS = trashlib
+
+NULL =
+
+mountdir = $(datadir)/gvfs/mounts
+
+INCLUDES = \
+ $(SAMBA_CFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/common \
+ -I$(top_builddir) \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+ $(OBEXFTP_CFLAGS) $(XML_CFLAGS) \
+ $(KEYRING_CFLAGS) \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ -DLIBEXEC_DIR=\"$(libexecdir)/\" \
+ -DMOUNTABLE_DIR=\"$(mountdir)/\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED
+
+noinst_LTLIBRARIES=libdaemon.la
+
+libraries = \
+ libdaemon.la \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(GLIB_LIBS) $(DBUS_LIBS) $(KEYRING_LIBS)
+
+# D-BUS service file
+%.service: %.service.in ../config.log
+ sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+servicedir = $(DBUS_SERVICE_DIR)
+service_in_files = gvfs-daemon.service.in
+service_DATA = gvfs-daemon.service
+
+%.mount: %.mount.in ../config.log
+ sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest
+
+mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in
+mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount
+
+mount_in_files += http.mount.in dav.mount.in dav+sd.mount.in ftp.mount.in
+if HAVE_HTTP
+mount_DATA += http.mount dav.mount ftp.mount
+if HAVE_AVAHI
+mount_DATA += dav+sd.mount
+endif
+libexec_PROGRAMS += gvfsd-http gvfsd-dav gvfsd-ftp
+endif
+
+mount_in_files += smb.mount.in smb-browse.mount.in
+if HAVE_SAMBA
+mount_DATA += smb.mount smb-browse.mount
+libexec_PROGRAMS += gvfsd-smb-browse gvfsd-smb
+endif
+
+mount_in_files += cdda.mount.in
+if USE_CDDA
+mount_DATA += cdda.mount
+libexec_PROGRAMS += gvfsd-cdda
+endif
+
+mount_in_files += gphoto2.mount.in
+if USE_GPHOTO2
+mount_DATA += gphoto2.mount
+libexec_PROGRAMS += gvfsd-gphoto2
+endif
+
+mount_in_files += network.mount.in
+if USE_GCONF
+mount_DATA += network.mount
+libexec_PROGRAMS += gvfsd-network
+endif
+
+mount_in_files += obexftp.mount.in
+if USE_OBEXFTP
+mount_DATA += obexftp.mount
+libexec_PROGRAMS += gvfsd-obexftp
+BUILT_SOURCES = obexftp-marshal.c obexftp-marshal.h
+
+obexftp-marshal.h: obexftp-marshal.list
+ glib-genmarshal $< --prefix=obexftp_marshal --header > $@
+
+obexftp-marshal.c: obexftp-marshal.list
+ echo "#include \"obexftp-marshal.h\"" > $@ && glib-genmarshal $< --prefix=obexftp_marshal --body >> $@
+
+endif
+
+mount_in_files += dns-sd.mount.in
+if HAVE_AVAHI
+mount_DATA += dns-sd.mount
+libexec_PROGRAMS += gvfsd-dnssd
+endif
+
+mount_in_files += archive.mount.in
+if HAVE_ARCHIVE
+mount_DATA += archive.mount
+libexec_PROGRAMS += gvfsd-archive
+endif
+
+EXTRA_DIST = gvfs-daemon.service.in $(mount_in_files) obexftp-marshal.list
+
+DISTCLEANFILES = gvfs-daemon.service $(mount_DATA)
+
+
+noinst_PROGRAMS = \
+ gvfsd-test \
+ $(NULL)
+
+libdaemon_la_SOURCES = \
+ gvfsdaemon.c gvfsdaemon.h \
+ gvfsbackend.c gvfsbackend.h \
+ gvfschannel.c gvfschannel.h \
+ gvfsreadchannel.c gvfsreadchannel.h \
+ gvfswritechannel.c gvfswritechannel.h \
+ gvfsmonitor.c gvfsmonitor.h \
+ gvfsdaemonutils.c gvfsdaemonutils.h \
+ gvfsjob.c gvfsjob.h \
+ gvfsjobsource.c gvfsjobsource.h \
+ gvfsjobdbus.c gvfsjobdbus.h \
+ gvfsjobmount.c gvfsjobmount.h \
+ gvfsjobunmount.c gvfsjobunmount.h \
+ gvfsjobmountmountable.c gvfsjobmountmountable.h \
+ gvfsjobunmountmountable.c gvfsjobunmountmountable.h \
+ gvfsjobopenforread.c gvfsjobopenforread.h \
+ gvfsjobopeniconforread.c gvfsjobopeniconforread.h \
+ gvfsjobread.c gvfsjobread.h \
+ gvfsjobseekread.c gvfsjobseekread.h \
+ gvfsjobcloseread.c gvfsjobcloseread.h \
+ gvfsjobopenforwrite.c gvfsjobopenforwrite.h \
+ gvfsjobwrite.c gvfsjobwrite.h \
+ gvfsjobseekwrite.c gvfsjobseekwrite.h \
+ gvfsjobclosewrite.c gvfsjobclosewrite.h \
+ gvfsjobqueryinfo.c gvfsjobqueryinfo.h \
+ gvfsjobqueryinforead.c gvfsjobqueryinforead.h \
+ gvfsjobqueryinfowrite.c gvfsjobqueryinfowrite.h \
+ gvfsjobqueryfsinfo.c gvfsjobqueryfsinfo.h \
+ gvfsjobenumerate.c gvfsjobenumerate.h \
+ gvfsjobsetdisplayname.c gvfsjobsetdisplayname.h \
+ gvfsjobtrash.c gvfsjobtrash.h \
+ gvfsjobdelete.c gvfsjobdelete.h \
+ gvfsjobcopy.c gvfsjobcopy.h \
+ gvfsjobmove.c gvfsjobmove.h \
+ gvfsjobpush.c gvfsjobpush.h \
+ gvfsjobpull.c gvfsjobpull.h \
+ gvfsjobmakedirectory.c gvfsjobmakedirectory.h \
+ gvfsjobmakesymlink.c gvfsjobmakesymlink.h \
+ gvfsjobsetattribute.c gvfsjobsetattribute.h \
+ gvfsjobqueryattributes.c gvfsjobqueryattributes.h \
+ gvfsjobcreatemonitor.c gvfsjobcreatemonitor.h \
+ dbus-gmain.h dbus-gmain.c \
+ gvfskeyring.h gvfskeyring.c \
+ $(NULL)
+
+gvfsd_SOURCES = \
+ mount.c mount.h \
+ main.c
+
+gvfsd_LDADD = $(libraries)
+
+gvfsd_test_SOURCES = \
+ gvfsbackendtest.c gvfsbackendtest.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_test_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendtest.h \
+ -DDEFAULT_BACKEND_TYPE=test \
+ -DBACKEND_TYPES='"test", G_VFS_TYPE_BACKEND_TEST,'
+
+gvfsd_test_LDADD = $(libraries)
+
+gvfsd_localtest_SOURCES = \
+ gvfsbackendlocaltest.c gvfsbackendlocaltest.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_localtest_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendlocaltest.h \
+ -DDEFAULT_BACKEND_TYPE=localtest \
+ -DBACKEND_TYPES='"localtest", G_VFS_TYPE_BACKEND_LOCALTEST,'
+
+gvfsd_localtest_LDADD = $(libraries)
+
+gvfsd_smb_SOURCES = \
+ gvfsbackendsmb.c gvfsbackendsmb.h libsmb-compat.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_smb_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendsmb.h \
+ -DDEFAULT_BACKEND_TYPE=smb-share \
+ -DMAX_JOB_THREADS=1 \
+ $(GCONF_CFLAGS) \
+ -DBACKEND_TYPES='"smb-share", G_VFS_TYPE_BACKEND_SMB,'
+
+gvfsd_smb_LDADD = $(SAMBA_LIBS) $(GCONF_LIBS) $(libraries)
+
+gvfsd_smb_browse_SOURCES = \
+ gvfsbackendsmbbrowse.c gvfsbackendsmbbrowse.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_smb_browse_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendsmbbrowse.h \
+ -DMOUNTABLE_DBUS_NAME=org.gtk.vfs.mountpoint.smb_browse \
+ -DMAX_JOB_THREADS=1 \
+ $(GCONF_CFLAGS) \
+ -DBACKEND_TYPES='"smb-network", G_VFS_TYPE_BACKEND_SMB_BROWSE,"smb-server", G_VFS_TYPE_BACKEND_SMB_BROWSE,'
+
+gvfsd_smb_browse_LDADD = $(SAMBA_LIBS) $(GCONF_LIBS) $(libraries)
+
+gvfsd_obexftp_SOURCES = \
+ gvfsbackendobexftp.c gvfsbackendobexftp.h \
+ obexftp-marshal.c obexftp-marshal.h \
+ gvfsbackendobexftp-fl-parser.c gvfsbackendobexftp-fl-parser.h \
+ gvfsbackendobexftp-cap-parser.c gvfsbackendobexftp-cap-parser.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_obexftp_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendobexftp.h \
+ -DDEFAULT_BACKEND_TYPE=obex \
+ -DMAX_JOB_THREADS=1 \
+ $(HAL_CFLAGS) \
+ -DBACKEND_TYPES='"obex", G_VFS_TYPE_BACKEND_OBEXFTP,'
+
+gvfsd_obexftp_LDADD = $(OBEXFTP_LIBS) $(XML_LIBS) $(HAL_LIBS) $(libraries)
+
+gvfsd_ftp_SOURCES = \
+ gvfsbackendftp.c gvfsbackendftp.h \
+ ParseFTPList.c ParseFTPList.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_ftp_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendftp.h \
+ -DDEFAULT_BACKEND_TYPE=ftp \
+ -DMAX_JOB_THREADS=10 \
+ $(HTTP_CFLAGS) \
+ -DBACKEND_TYPES='"ftp", G_VFS_TYPE_BACKEND_FTP,'
+
+gvfsd_ftp_LDADD = $(libraries) $(HTTP_LIBS)
+
+gvfsd_sftp_SOURCES = \
+ sftp.h \
+ gvfsbackendsftp.c gvfsbackendsftp.h \
+ pty_open.c pty_open.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_sftp_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendsftp.h \
+ -DDEFAULT_BACKEND_TYPE=sftp \
+ -DMAX_JOB_THREADS=1 \
+ -DSSH_PROGRAM=\"$(SSH_PROGRAM)\" \
+ -DBACKEND_TYPES='"sftp", G_VFS_TYPE_BACKEND_SFTP,'
+
+gvfsd_sftp_LDADD = $(libraries)
+
+gvfsd_trash_SOURCES = \
+ gvfsbackendtrash.c gvfsbackendtrash.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_trash_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendtrash.h \
+ -DDEFAULT_BACKEND_TYPE=trash \
+ -DMAX_JOB_THREADS=10 \
+ -DBACKEND_TYPES='"trash", G_VFS_TYPE_BACKEND_TRASH,' \
+ -Itrashlib
+
+gvfsd_trash_LDADD = $(libraries) trashlib/libtrash.a
+
+gvfsd_computer_SOURCES = \
+ gvfsbackendcomputer.c gvfsbackendcomputer.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_computer_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendcomputer.h \
+ -DDEFAULT_BACKEND_TYPE=computer \
+ -DMAX_JOB_THREADS=1 \
+ -DBACKEND_TYPES='"computer", G_VFS_TYPE_BACKEND_COMPUTER,'
+
+gvfsd_computer_LDADD = $(libraries)
+
+gvfsd_network_SOURCES = \
+ gvfsbackendnetwork.c gvfsbackendnetwork.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_network_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendnetwork.h \
+ -DDEFAULT_BACKEND_TYPE=network \
+ -DMAX_JOB_THREADS=1 \
+ $(GCONF_CFLAGS) \
+ -DBACKEND_TYPES='"network", G_VFS_TYPE_BACKEND_NETWORK,'
+
+gvfsd_network_LDADD = $(libraries) $(GCONF_LIBS)
+
+gvfsd_dnssd_SOURCES = \
+ gvfsbackenddnssd.c gvfsbackenddnssd.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_dnssd_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackenddnssd.h \
+ -DDEFAULT_BACKEND_TYPE=dns-sd \
+ -DMAX_JOB_THREADS=1 \
+ $(AVAHI_CFLAGS) \
+ -DBACKEND_TYPES='"dns-sd", G_VFS_TYPE_BACKEND_DNS_SD,'
+
+gvfsd_dnssd_LDADD = $(libraries) $(AVAHI_LIBS) $(top_builddir)/common/libgvfscommon-dnssd.la
+
+
+gvfsd_archive_SOURCES = \
+ gvfsbackendarchive.c gvfsbackendarchive.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_archive_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendarchive.h \
+ -DDEFAULT_BACKEND_TYPE=archive \
+ -DMAX_JOB_THREADS=1 \
+ $(ARCHIVE_CFLAGS) \
+ -DBACKEND_TYPES='"archive", G_VFS_TYPE_BACKEND_ARCHIVE,'
+
+gvfsd_archive_LDADD = $(libraries) $(ARCHIVE_LIBS)
+
+gvfsd_burn_SOURCES = \
+ gvfsbackendburn.c gvfsbackendburn.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_burn_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendburn.h \
+ -DDEFAULT_BACKEND_TYPE=burn \
+ -DMAX_JOB_THREADS=1 \
+ -DBACKEND_TYPES='"burn", G_VFS_TYPE_BACKEND_BURN,'
+
+gvfsd_burn_LDADD = $(libraries)
+
+gvfsd_cdda_SOURCES = \
+ gvfsbackendcdda.c gvfsbackendcdda.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_cdda_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendcdda.h \
+ -DDEFAULT_BACKEND_TYPE=cdda \
+ -DMAX_JOB_THREADS=1 \
+ $(CDDA_CFLAGS) $(HAL_CFLAGS) \
+ -DBACKEND_TYPES='"cdda", G_VFS_TYPE_BACKEND_CDDA,'
+
+gvfsd_cdda_LDADD = $(libraries) $(CDDA_LIBS) $(HAL_LIBS)
+
+gvfsd_gphoto2_SOURCES = \
+ gvfsbackendgphoto2.c gvfsbackendgphoto2.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_gphoto2_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendgphoto2.h \
+ -DDEFAULT_BACKEND_TYPE=gphoto2 \
+ -DMAX_JOB_THREADS=1 \
+ $(GPHOTO2_CFLAGS) $(HAL_CFLAGS) \
+ -DBACKEND_TYPES='"gphoto2", G_VFS_TYPE_BACKEND_GPHOTO2,'
+
+gvfsd_gphoto2_LDADD = $(libraries) $(GPHOTO2_LIBS) $(HAL_LIBS)
+
+gvfsd_http_SOURCES = \
+ soup-input-stream.c soup-input-stream.h \
+ soup-output-stream.c soup-output-stream.h \
+ gvfsbackendhttp.c gvfsbackendhttp.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_http_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackendhttp.h \
+ -DMOUNTABLE_DBUS_NAME=org.gtk.vfs.mountpoint.http \
+ -DDEFAULT_BACKEND_TYPE=http \
+ -DMAX_JOB_THREADS=1 \
+ $(HTTP_CFLAGS) \
+ -DBACKEND_TYPES='"http", G_VFS_TYPE_BACKEND_HTTP,'
+
+gvfsd_http_LDADD = $(libraries) $(HTTP_LIBS)
+
+gvfsd_dav_SOURCES = \
+ soup-input-stream.c soup-input-stream.h \
+ soup-output-stream.c soup-output-stream.h \
+ gvfsbackendhttp.c gvfsbackendhttp.h \
+ gvfsbackenddav.c gvfsbackenddav.h \
+ daemon-main.c daemon-main.h \
+ daemon-main-generic.c
+
+gvfsd_dav_CPPFLAGS = \
+ -DBACKEND_HEADER=gvfsbackenddav.h \
+ -DDEFAULT_BACKEND_TYPE=dav \
+ -DMAX_JOB_THREADS=1 \
+ $(HTTP_CFLAGS)
+
+if HAVE_AVAHI
+gvfsd_dav_CPPFLAGS += -DBACKEND_TYPES='"dav", G_VFS_TYPE_BACKEND_DAV, "dav+sd", G_VFS_TYPE_BACKEND_DAV, "davs+sd", G_VFS_TYPE_BACKEND_DAV,'
+else
+gvfsd_dav_CPPFLAGS += -DBACKEND_TYPES='"dav", G_VFS_TYPE_BACKEND_DAV,'
+endif
+
+gvfsd_dav_LDADD = $(libraries) $(HTTP_LIBS)
+if HAVE_AVAHI
+gvfsd_dav_LDADD += $(top_builddir)/common/libgvfscommon-dnssd.la
+endif
diff --git a/trunk/daemon/ParseFTPList.c b/trunk/daemon/ParseFTPList.c
new file mode 100644
index 00000000..3b261a29
--- /dev/null
+++ b/trunk/daemon/ParseFTPList.c
@@ -0,0 +1,1842 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Cyrus Patel <cyp@fb14.uni-mainz.de>.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "ParseFTPList.h"
+
+/* ==================================================================== */
+
+int ParseFTPList(const char *line, struct list_state *state,
+ struct list_result *result )
+{
+ unsigned int carry_buf_len; /* copy of state->carry_buf_len */
+ unsigned int linelen, pos;
+ const char *p;
+
+ if (!line || !state || !result)
+ return 0;
+
+ memset( result, 0, sizeof(*result) );
+ if (state->magic != ((void *)ParseFTPList))
+ {
+ memset( state, 0, sizeof(*state) );
+ state->magic = ((void *)ParseFTPList);
+ }
+ state->numlines++;
+
+ /* carry buffer is only valid from one line to the next */
+ carry_buf_len = state->carry_buf_len;
+ state->carry_buf_len = 0;
+
+ linelen = 0;
+
+ /* strip leading whitespace */
+ while (*line == ' ' || *line == '\t')
+ line++;
+
+ /* line is terminated at first '\0' or '\n' */
+ p = line;
+ while (*p && *p != '\n')
+ p++;
+ linelen = p - line;
+
+ if (linelen > 0 && *p == '\n' && *(p-1) == '\r')
+ linelen--;
+
+ /* DON'T strip trailing whitespace. */
+
+ if (linelen > 0)
+ {
+ static const char *month_names = "JanFebMarAprMayJunJulAugSepOctNovDec";
+ const char *tokens[16]; /* 16 is more than enough */
+ unsigned int toklen[(sizeof(tokens)/sizeof(tokens[0]))];
+ unsigned int linelen_sans_wsp; // line length sans whitespace
+ unsigned int numtoks = 0;
+ unsigned int tokmarker = 0; /* extra info for lstyle handler */
+ unsigned int month_num = 0;
+ char tbuf[4];
+ int lstyle = 0;
+
+ if (carry_buf_len) /* VMS long filename carryover buffer */
+ {
+ tokens[0] = state->carry_buf;
+ toklen[0] = carry_buf_len;
+ numtoks++;
+ }
+
+ pos = 0;
+ while (pos < linelen && numtoks < (sizeof(tokens)/sizeof(tokens[0])) )
+ {
+ while (pos < linelen &&
+ (line[pos] == ' ' || line[pos] == '\t' || line[pos] == '\r'))
+ pos++;
+ if (pos < linelen)
+ {
+ tokens[numtoks] = &line[pos];
+ while (pos < linelen &&
+ (line[pos] != ' ' && line[pos] != '\t' && line[pos] != '\r'))
+ pos++;
+ if (tokens[numtoks] != &line[pos])
+ {
+ toklen[numtoks] = (&line[pos] - tokens[numtoks]);
+ numtoks++;
+ }
+ }
+ }
+
+ linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0];
+ if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) )
+ {
+ pos = linelen;
+ while (pos > 0 && (line[pos-1] == ' ' || line[pos-1] == '\t'))
+ pos--;
+ linelen_sans_wsp = pos;
+ }
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_EPLF)
+ /* EPLF handling must come somewhere before /bin/dls handling. */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'E'))
+ {
+ if (*line == '+' && linelen > 4 && numtoks >= 2)
+ {
+ pos = 1;
+ while (pos < (linelen-1))
+ {
+ p = &line[pos++];
+ if (*p == '/')
+ result->fe_type = 'd'; /* its a dir */
+ else if (*p == 'r')
+ result->fe_type = 'f'; /* its a file */
+ else if (*p == 'm')
+ {
+ if (isdigit(line[pos]))
+ {
+ while (pos < linelen && isdigit(line[pos]))
+ pos++;
+ if (pos < linelen && line[pos] == ',')
+ {
+ guint64 seconds;
+ time_t t;
+ sscanf(p+1, "%"G_GUINT64_FORMAT, &seconds);
+ t = seconds;
+ result->fe_time = *localtime (&t);
+ }
+ }
+ }
+ else if (*p == 's')
+ {
+ if (isdigit(line[pos]))
+ {
+ while (pos < linelen && isdigit(line[pos]))
+ pos++;
+ if (pos < linelen && line[pos] == ',' &&
+ ((&line[pos]) - (p+1)) < (int) (sizeof(result->fe_size)-1) )
+ {
+ memcpy( result->fe_size, p+1, (unsigned)(&line[pos] - (p+1)) );
+ result->fe_size[(&line[pos] - (p+1))] = '\0';
+ }
+ }
+ }
+ else if (isalpha(*p)) /* 'i'/'up' or unknown "fact" (property) */
+ {
+ while (pos < linelen && *++p != ',')
+ pos++;
+ }
+ else if (*p != '\t' || (p+1) != tokens[1])
+ {
+ break; /* its not EPLF after all */
+ }
+ else
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle = 'E';
+
+ p = &(line[linelen_sans_wsp]);
+ result->fe_fname = tokens[1];
+ result->fe_fnlen = p - tokens[1];
+
+ if (!result->fe_type) /* access denied */
+ {
+ result->fe_type = 'f'; /* is assuming 'f'ile correct? */
+ return '?'; /* NO! junk it. */
+ }
+ return result->fe_type;
+ }
+ if (pos >= (linelen-1) || line[pos] != ',')
+ break;
+ pos++;
+ } /* while (pos < linelen) */
+ memset( result, 0, sizeof(*result) );
+ } /* if (*line == '+' && linelen > 4 && numtoks >= 2) */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'E')) */
+#endif /* SUPPORT_EPLF */
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_VMS)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'V'))
+ { /* try VMS Multinet/UCX/CMS server */
+ /*
+ * Legal characters in a VMS file/dir spec are [A-Z0-9$.-_~].
+ * '$' cannot begin a filename and `-' cannot be used as the first
+ * or last character. '.' is only valid as a directory separator
+ * and <file>.<type> separator. A canonical filename spec might look
+ * like this: DISK$VOL:[DIR1.DIR2.DIR3]FILE.TYPE;123
+ * All VMS FTP servers LIST in uppercase.
+ *
+ * We need to be picky about this in order to support
+ * multi-line listings correctly.
+ */
+ if (!state->parsed_one &&
+ (numtoks == 1 || (numtoks == 2 && toklen[0] == 9 &&
+ memcmp(tokens[0], "Directory", 9)==0 )))
+ {
+ /* If no dirstyle has been detected yet, and this line is a
+ * VMS list's dirname, then turn on VMS dirstyle.
+ * eg "ACA:[ANONYMOUS]", "DISK$FTP:[ANONYMOUS]", "SYS$ANONFTP:"
+ */
+ p = tokens[0];
+ pos = toklen[0];
+ if (numtoks == 2)
+ {
+ p = tokens[1];
+ pos = toklen[1];
+ }
+ pos--;
+ if (pos >= 3)
+ {
+ while (pos > 0 && p[pos] != '[')
+ {
+ pos--;
+ if (p[pos] == '-' || p[pos] == '$')
+ {
+ if (pos == 0 || p[pos-1] == '[' || p[pos-1] == '.' ||
+ (p[pos] == '-' && (p[pos+1] == ']' || p[pos+1] == '.')))
+ break;
+ }
+ else if (p[pos] != '.' && p[pos] != '~' &&
+ !isdigit(p[pos]) && !isalpha(p[pos]))
+ break;
+ else if (isalpha(p[pos]) && p[pos] != toupper(p[pos]))
+ break;
+ }
+ if (pos > 0)
+ {
+ pos--;
+ if (p[pos] != ':' || p[pos+1] != '[')
+ pos = 0;
+ }
+ }
+ if (pos > 0 && p[pos] == ':')
+ {
+ while (pos > 0)
+ {
+ pos--;
+ if (p[pos] != '$' && p[pos] != '_' && p[pos] != '-' &&
+ p[pos] != '~' && !isdigit(p[pos]) && !isalpha(p[pos]))
+ break;
+ else if (isalpha(p[pos]) && p[pos] != toupper(p[pos]))
+ break;
+ }
+ if (pos == 0)
+ {
+ state->lstyle = 'V';
+ return '?'; /* its junk */
+ }
+ }
+ /* fallthrough */
+ }
+ else if ((tokens[0][toklen[0]-1]) != ';')
+ {
+ if (numtoks == 1 && (state->lstyle == 'V' && !carry_buf_len))
+ lstyle = 'V';
+ else if (numtoks < 4)
+ ;
+ else if (toklen[1] >= 10 && memcmp(tokens[1], "%RMS-E-PRV", 10) == 0)
+ lstyle = 'V';
+ else if ((&line[linelen] - tokens[1]) >= 22 &&
+ memcmp(tokens[1], "insufficient privilege", 22) == 0)
+ lstyle = 'V';
+ else if (numtoks != 4 && numtoks != 6)
+ ;
+ else if (numtoks == 6 && (
+ toklen[5] < 4 || *tokens[5] != '(' || /* perms */
+ (tokens[5][toklen[5]-1]) != ')' ))
+ ;
+ else if ( (toklen[2] == 10 || toklen[2] == 11) &&
+ (tokens[2][toklen[2]-5]) == '-' &&
+ (tokens[2][toklen[2]-9]) == '-' &&
+ (((toklen[3]==4 || toklen[3]==5 || toklen[3]==7 || toklen[3]==8) &&
+ (tokens[3][toklen[3]-3]) == ':' ) ||
+ ((toklen[3]==10 || toklen[3]==11 ) &&
+ (tokens[3][toklen[3]-3]) == '.' )
+ ) && /* time in [H]H:MM[:SS[.CC]] format */
+ isdigit(*tokens[1]) && /* size */
+ isdigit(*tokens[2]) && /* date */
+ isdigit(*tokens[3]) /* time */
+ )
+ {
+ lstyle = 'V';
+ }
+ if (lstyle == 'V')
+ {
+ /*
+ * MultiNet FTP:
+ * LOGIN.COM;2 1 4-NOV-1994 04:09 [ANONYMOUS] (RWE,RWE,,)
+ * PUB.DIR;1 1 27-JAN-1994 14:46 [ANONYMOUS] (RWE,RWE,RE,RWE)
+ * README.FTP;1 %RMS-E-PRV, insufficient privilege or file protection violation
+ * ROUSSOS.DIR;1 1 27-JAN-1994 14:48 [CS,ROUSSOS] (RWE,RWE,RE,R)
+ * S67-50903.JPG;1 328 22-SEP-1998 16:19 [ANONYMOUS] (RWED,RWED,,)
+ * UCX FTP:
+ * CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+ * CMU/VMS-IP FTP
+ * [VMSSERV.FILES]ALARM.DIR;1 1/3 5-MAR-1993 18:09
+ * TCPware FTP
+ * FOO.BAR;1 4 5-MAR-1993 18:09:01.12
+ * Long filename example:
+ * THIS-IS-A-LONG-VMS-FILENAME.AND-THIS-IS-A-LONG-VMS-FILETYPE\r\n
+ * 213[/nnn] 29-JAN-1996 03:33[:nn] [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+ */
+ tokmarker = 0;
+ p = tokens[0];
+ pos = 0;
+ if (*p == '[' && toklen[0] >= 4) /* CMU style */
+ {
+ if (p[1] != ']')
+ {
+ p++;
+ pos++;
+ }
+ while (lstyle && pos < toklen[0] && *p != ']')
+ {
+ if (*p != '$' && *p != '.' && *p != '_' && *p != '-' &&
+ *p != '~' && !isdigit(*p) && !isalpha(*p))
+ lstyle = 0;
+ pos++;
+ p++;
+ }
+ if (lstyle && pos < (toklen[0]-1) && *p == ']')
+ {
+ pos++;
+ p++;
+ tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */
+ }
+ }
+ while (lstyle && pos < toklen[0] && *p != ';')
+ {
+ if (*p != '$' && *p != '.' && *p != '_' && *p != '-' &&
+ *p != '~' && !isdigit(*p) && !isalpha(*p))
+ lstyle = 0;
+ else if (isalpha(*p) && *p != toupper(*p))
+ lstyle = 0;
+ p++;
+ pos++;
+ }
+ if (lstyle && *p == ';')
+ {
+ if (pos == 0 || pos == (toklen[0]-1))
+ lstyle = 0;
+ for (pos++;lstyle && pos < toklen[0];pos++)
+ {
+ if (!isdigit(tokens[0][pos]))
+ lstyle = 0;
+ }
+ }
+ pos = (p - tokens[0]); /* => fnlength sans ";####" */
+ pos -= tokmarker; /* => fnlength sans "[DIR1.DIR2.etc]" */
+ p = &(tokens[0][tokmarker]); /* offset of basename */
+
+ if (!lstyle || pos > 80) /* VMS filenames can't be longer than that */
+ {
+ lstyle = 0;
+ }
+ else if (numtoks == 1)
+ {
+ /* if VMS has been detected and there is only one token and that
+ * token was a VMS filename then this is a multiline VMS LIST entry.
+ */
+ if (pos >= (sizeof(state->carry_buf)-1))
+ pos = (sizeof(state->carry_buf)-1); /* shouldn't happen */
+ memcpy( state->carry_buf, p, pos );
+ state->carry_buf_len = pos;
+ return '?'; /* tell caller to treat as junk */
+ }
+ else if (isdigit(*tokens[1])) /* not no-privs message */
+ {
+ for (pos = 0; lstyle && pos < (toklen[1]); pos++)
+ {
+ if (!isdigit((tokens[1][pos])) && (tokens[1][pos]) != '/')
+ lstyle = 0;
+ }
+ if (lstyle && numtoks > 4) /* Multinet or UCX but not CMU */
+ {
+ for (pos = 1; lstyle && pos < (toklen[5]-1); pos++)
+ {
+ p = &(tokens[5][pos]);
+ if (*p!='R' && *p!='W' && *p!='E' && *p!='D' && *p!=',')
+ lstyle = 0;
+ }
+ }
+ }
+ } /* passed initial tests */
+ } /* else if ((tokens[0][toklen[0]-1]) != ';') */
+
+ if (lstyle == 'V')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ if (isdigit(*tokens[1])) /* not permission denied etc */
+ {
+ /* strip leading directory name */
+ if (*tokens[0] == '[') /* CMU server */
+ {
+ pos = toklen[0]-1;
+ p = tokens[0]+1;
+ while (*p != ']')
+ {
+ p++;
+ pos--;
+ }
+ toklen[0] = --pos;
+ tokens[0] = ++p;
+ }
+ pos = 0;
+ while (pos < toklen[0] && (tokens[0][pos]) != ';')
+ pos++;
+
+ result->fe_cinfs = 1;
+ result->fe_type = 'f';
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = pos;
+
+ if (pos > 4)
+ {
+ p = &(tokens[0][pos-4]);
+ if (p[0] == '.' && p[1] == 'D' && p[2] == 'I' && p[3] == 'R')
+ {
+ result->fe_fnlen -= 4;
+ result->fe_type = 'd';
+ }
+ }
+
+ if (result->fe_type != 'd')
+ {
+ /* #### or used/allocated form. If used/allocated form, then
+ * 'used' is the size in bytes if and only if 'used'<=allocated.
+ * If 'used' is size in bytes then it can be > 2^32
+ * If 'used' is not size in bytes then it is size in blocks.
+ */
+ pos = 0;
+ while (pos < toklen[1] && (tokens[1][pos]) != '/')
+ pos++;
+
+/*
+ * I've never seen size come back in bytes, its always in blocks, and
+ * the following test fails. So, always perform the "size in blocks".
+ * I'm leaving the "size in bytes" code if'd out in case we ever need
+ * to re-instate it.
+*/
+#if 0
+ if (pos < toklen[1] && ( (pos<<1) > (toklen[1]-1) ||
+ (strtoul(tokens[1], (char **)0, 10) >
+ strtoul(tokens[1]+pos+1, (char **)0, 10)) ))
+ { /* size is in bytes */
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, tokens[1], pos );
+ result->fe_size[pos] = '\0';
+ }
+ else /* size is in blocks */
+#endif
+ {
+ /* size requires multiplication by blocksize.
+ *
+ * We could assume blocksize is 512 (like Lynx does) and
+ * shift by 9, but that might not be right. Even if it
+ * were, doing that wouldn't reflect what the file's
+ * real size was. The sanest thing to do is not use the
+ * LISTing's filesize, so we won't (like ftpmirror).
+ *
+ * ulltoa(((unsigned long long)fsz)<<9, result->fe_size, 10);
+ *
+ * A block is always 512 bytes on OpenVMS, compute size.
+ * So its rounded up to the next block, so what, its better
+ * than not showing the size at all.
+ * A block is always 512 bytes on OpenVMS, compute size.
+ * So its rounded up to the next block, so what, its better
+ * than not showing the size at all.
+ */
+ guint64 fsz;
+ fsz = g_ascii_strtoull (tokens[1], (char **)0, 10);
+ fsz *= 512;
+ g_snprintf(result->fe_size, sizeof(result->fe_size),
+ "%"G_GUINT64_FORMAT, fsz);
+ }
+
+ } /* if (result->fe_type != 'd') */
+
+ p = tokens[2] + 2;
+ if (*p == '-')
+ p++;
+ tbuf[0] = p[0];
+ tbuf[1] = tolower(p[1]);
+ tbuf[2] = tolower(p[2]);
+ month_num = 0;
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (tbuf[0] == month_names[pos+0] &&
+ tbuf[1] == month_names[pos+1] &&
+ tbuf[2] == month_names[pos+2])
+ break;
+ month_num++;
+ }
+ if (month_num >= 12)
+ month_num = 0;
+ result->fe_time.tm_mon = month_num;
+ result->fe_time.tm_mday = atoi(tokens[2]);
+ result->fe_time.tm_year = atoi(p+4); // NSPR wants year as XXXX
+
+ p = tokens[3] + 2;
+ if (*p == ':')
+ p++;
+ if (p[2] == ':')
+ result->fe_time.tm_sec = atoi(p+3);
+ result->fe_time.tm_hour = atoi(tokens[3]);
+ result->fe_time.tm_min = atoi(p);
+
+ return result->fe_type;
+
+ } /* if (isdigit(*tokens[1])) */
+
+ return '?'; /* junk */
+
+ } /* if (lstyle == 'V') */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'V')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_CMS)
+ /* Virtual Machine/Conversational Monitor System (IBM Mainframe) */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'C')) /* VM/CMS */
+ {
+ /* LISTing according to mirror.pl
+ * Filename FileType Fm Format Lrecl Records Blocks Date Time
+ * LASTING GLOBALV A1 V 41 21 1 9/16/91 15:10:32
+ * J43401 NETLOG A0 V 77 1 1 9/12/91 12:36:04
+ * PROFILE EXEC A1 V 17 3 1 9/12/91 12:39:07
+ * DIRUNIX SCRIPT A1 V 77 1216 17 1/04/93 20:30:47
+ * MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27
+ * BADY2K TEXT A0 V 1 1 1 1/03/102 10:11:12
+ * AUTHORS A1 DIR - - - 9/20/99 10:31:11
+ *
+ * LISTing from vm.marist.edu and vm.sc.edu
+ * 220-FTPSERVE IBM VM Level 420 at VM.MARIST.EDU, 04:58:12 EDT WEDNESDAY 2002-07-10
+ * AUTHORS DIR - - - 1999-09-20 10:31:11 -
+ * HARRINGTON DIR - - - 1997-02-12 15:33:28 -
+ * PICS DIR - - - 2000-10-12 15:43:23 -
+ * SYSFILE DIR - - - 2000-07-20 17:48:01 -
+ * WELCNVT EXEC V 72 9 1 1999-09-20 17:16:18 -
+ * WELCOME EREADME F 80 21 1 1999-12-27 16:19:00 -
+ * WELCOME README V 82 21 1 1999-12-27 16:19:04 -
+ * README ANONYMOU V 71 26 1 1997-04-02 12:33:20 TCP291
+ * README ANONYOLD V 71 15 1 1995-08-25 16:04:27 TCP291
+ */
+ if (numtoks >= 7 && (toklen[0]+toklen[1]) <= 16)
+ {
+ for (pos = 1; !lstyle && (pos+5) < numtoks; pos++)
+ {
+ p = tokens[pos];
+ if ((toklen[pos] == 1 && (*p == 'F' || *p == 'V')) ||
+ (toklen[pos] == 3 && *p == 'D' && p[1] == 'I' && p[2] == 'R'))
+ {
+ if (toklen[pos+5] == 8 && (tokens[pos+5][2]) == ':' &&
+ (tokens[pos+5][5]) == ':' )
+ {
+ p = tokens[pos+4];
+ if ((toklen[pos+4] == 10 && p[4] == '-' && p[7] == '-') ||
+ (toklen[pos+4] >= 7 && toklen[pos+4] <= 9 &&
+ p[((p[1]!='/')?(2):(1))] == '/' &&
+ p[((p[1]!='/')?(5):(4))] == '/'))
+ /* Y2K bugs possible ("7/06/102" or "13/02/101") */
+ {
+ if ( (*tokens[pos+1] == '-' &&
+ *tokens[pos+2] == '-' &&
+ *tokens[pos+3] == '-') ||
+ (isdigit(*tokens[pos+1]) &&
+ isdigit(*tokens[pos+2]) &&
+ isdigit(*tokens[pos+3])) )
+ {
+ lstyle = 'C';
+ tokmarker = pos;
+ }
+ }
+ }
+ }
+ } /* for (pos = 1; !lstyle && (pos+5) < numtoks; pos++) */
+ } /* if (numtoks >= 7) */
+
+ /* extra checking if first pass */
+ if (lstyle && !state->lstyle)
+ {
+ for (pos = 0, p = tokens[0]; lstyle && pos < toklen[0]; pos++, p++)
+ {
+ if (isalpha(*p) && toupper(*p) != *p)
+ lstyle = 0;
+ }
+ for (pos = tokmarker+1; pos <= tokmarker+3; pos++)
+ {
+ if (!(toklen[pos] == 1 && *tokens[pos] == '-'))
+ {
+ for (p = tokens[pos]; lstyle && p<(tokens[pos]+toklen[pos]); p++)
+ {
+ if (!isdigit(*p))
+ lstyle = 0;
+ }
+ }
+ }
+ for (pos = 0, p = tokens[tokmarker+4];
+ lstyle && pos < toklen[tokmarker+4]; pos++, p++)
+ {
+ if (*p == '/')
+ {
+ /* There may be Y2K bugs in the date. Don't simplify to
+ * pos != (len-3) && pos != (len-6) like time is done.
+ */
+ if ((tokens[tokmarker+4][1]) == '/')
+ {
+ if (pos != 1 && pos != 4)
+ lstyle = 0;
+ }
+ else if (pos != 2 && pos != 5)
+ lstyle = 0;
+ }
+ else if (*p != '-' && !isdigit(*p))
+ lstyle = 0;
+ else if (*p == '-' && pos != 4 && pos != 7)
+ lstyle = 0;
+ }
+ for (pos = 0, p = tokens[tokmarker+5];
+ lstyle && pos < toklen[tokmarker+5]; pos++, p++)
+ {
+ if (*p != ':' && !isdigit(*p))
+ lstyle = 0;
+ else if (*p == ':' && pos != (toklen[tokmarker+5]-3)
+ && pos != (toklen[tokmarker+5]-6))
+ lstyle = 0;
+ }
+ } /* initial if() */
+
+ if (lstyle == 'C')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = tokens[tokmarker+4];
+ if (toklen[tokmarker+4] == 10) /* newstyle: YYYY-MM-DD format */
+ {
+ result->fe_time.tm_year = atoi(p+0) - 1900;
+ result->fe_time.tm_mon = atoi(p+5) - 1;
+ result->fe_time.tm_mday = atoi(p+8);
+ }
+ else /* oldstyle: [M]M/DD/YY format */
+ {
+ pos = toklen[tokmarker+4];
+ result->fe_time.tm_mon = atoi(p) - 1;
+ result->fe_time.tm_mday = atoi((p+pos)-5);
+ result->fe_time.tm_year = atoi((p+pos)-2);
+ if (result->fe_time.tm_year < 70)
+ result->fe_time.tm_year += 100;
+ }
+
+ p = tokens[tokmarker+5];
+ pos = toklen[tokmarker+5];
+ result->fe_time.tm_hour = atoi(p);
+ result->fe_time.tm_min = atoi((p+pos)-5);
+ result->fe_time.tm_sec = atoi((p+pos)-2);
+
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = toklen[0];
+ result->fe_type = 'f';
+
+ p = tokens[tokmarker];
+ if (toklen[tokmarker] == 3 && *p=='D' && p[1]=='I' && p[2]=='R')
+ result->fe_type = 'd';
+
+ if ((/*newstyle*/ toklen[tokmarker+4] == 10 && tokmarker > 1) ||
+ (/*oldstyle*/ toklen[tokmarker+4] != 10 && tokmarker > 2))
+ { /* have a filetype column */
+ char *dot;
+ p = &(tokens[0][toklen[0]]);
+ memcpy( &dot, &p, sizeof(dot) ); /* NASTY! */
+ *dot++ = '.';
+ p = tokens[1];
+ for (pos = 0; pos < toklen[1]; pos++)
+ *dot++ = *p++;
+ result->fe_fnlen += 1 + toklen[1];
+ }
+
+ /* oldstyle LISTING:
+ * files/dirs not on the 'A' minidisk are not RETRievable/CHDIRable
+ if (toklen[tokmarker+4] != 10 && *tokens[tokmarker-1] != 'A')
+ return '?';
+ */
+
+ /* VM/CMS LISTings have no usable filesize field.
+ * Have to use the 'SIZE' command for that.
+ */
+ return result->fe_type;
+
+ } /* if (lstyle == 'C' && (!state->lstyle || state->lstyle == lstyle)) */
+ } /* VM/CMS */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_DOS) /* WinNT DOS dirstyle */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'W'))
+ {
+ /*
+ * "10-23-00 01:27PM <DIR> veronist"
+ * "06-15-00 07:37AM <DIR> zoe"
+ * "07-14-00 01:35PM 2094926 canprankdesk.tif"
+ * "07-21-00 01:19PM 95077 Jon Kauffman Enjoys the Good Life.jpg"
+ * "07-21-00 01:19PM 52275 Name Plate.jpg"
+ * "07-14-00 01:38PM 2250540 Valentineoffprank-HiRes.jpg"
+ */
+ if ((numtoks >= 4) && toklen[0] == 8 && toklen[1] == 7 &&
+ (*tokens[2] == '<' || isdigit(*tokens[2])) )
+ {
+ p = tokens[0];
+ if ( isdigit(p[0]) && isdigit(p[1]) && p[2]=='-' &&
+ isdigit(p[3]) && isdigit(p[4]) && p[5]=='-' &&
+ isdigit(p[6]) && isdigit(p[7]) )
+ {
+ p = tokens[1];
+ if ( isdigit(p[0]) && isdigit(p[1]) && p[2]==':' &&
+ isdigit(p[3]) && isdigit(p[4]) &&
+ (p[5]=='A' || p[5]=='P') && p[6]=='M')
+ {
+ lstyle = 'W';
+ if (!state->lstyle)
+ {
+ p = tokens[2];
+ /* <DIR> or <JUNCTION> */
+ if (*p != '<' || p[toklen[2]-1] != '>')
+ {
+ for (pos = 1; (lstyle && pos < toklen[2]); pos++)
+ {
+ if (!isdigit(*++p))
+ lstyle = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (lstyle == 'W')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(line[linelen_sans_wsp]); /* line end sans wsp */
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[3];
+ result->fe_fnlen = p - tokens[3];
+ result->fe_type = 'd';
+
+ if (*tokens[2] != '<') /* not <DIR> or <JUNCTION> */
+ {
+ result->fe_type = 'f';
+ pos = toklen[2];
+ while (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[2], pos );
+ result->fe_size[pos] = '\0';
+ }
+ else if ((tokens[2][1]) != 'D') /* not <DIR> */
+ {
+ result->fe_type = '?'; /* unknown until junc for sure */
+ if (result->fe_fnlen > 4)
+ {
+ p = result->fe_fname;
+ for (pos = result->fe_fnlen - 4; pos > 0; pos--)
+ {
+ if (p[0] == ' ' && p[3] == ' ' && p[2] == '>' &&
+ (p[1] == '=' || p[1] == '-'))
+ {
+ result->fe_type = 'l';
+ result->fe_fnlen = p - result->fe_fname;
+ result->fe_lname = p + 4;
+ result->fe_lnlen = &(line[linelen_sans_wsp])
+ - result->fe_lname;
+ break;
+ }
+ p++;
+ }
+ }
+ }
+
+ result->fe_time.tm_mon = atoi(tokens[0]+0);
+ if (result->fe_time.tm_mon != 0)
+ {
+ result->fe_time.tm_mon--;
+ result->fe_time.tm_mday = atoi(tokens[0]+3);
+ result->fe_time.tm_year = atoi(tokens[0]+6);
+ if (result->fe_time.tm_year < 80)
+ result->fe_time.tm_year += 100;
+ }
+
+ result->fe_time.tm_hour = atoi(tokens[1]+0);
+ result->fe_time.tm_min = atoi(tokens[1]+3);
+ if ((tokens[1][5]) == 'P' && result->fe_time.tm_hour < 12)
+ result->fe_time.tm_hour += 12;
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* if (lstyle == 'W' && (!state->lstyle || state->lstyle == lstyle)) */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'W')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_OS2)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'O')) /* OS/2 test */
+ {
+ /* 220 server IBM TCP/IP for OS/2 - FTP Server ver 23:04:36 on Jan 15 1997 ready.
+ * fixed position, space padded columns. I have only a vague idea
+ * of what the contents between col 18 and 34 might be: All I can infer
+ * is that there may be attribute flags in there and there may be
+ * a " DIR" in there.
+ *
+ * 1 2 3 4 5 6
+ *0123456789012345678901234567890123456789012345678901234567890123456789
+ *----- size -------|??????????????? MM-DD-YY| HH:MM| nnnnnnnnn....
+ * 0 DIR 04-11-95 16:26 .
+ * 0 DIR 04-11-95 16:26 ..
+ * 0 DIR 04-11-95 16:26 ADDRESS
+ * 612 RHSA 07-28-95 16:45 air_tra1.bag
+ * 195 A 08-09-95 10:23 Alfa1.bag
+ * 0 RHS DIR 04-11-95 16:26 ATTACH
+ * 372 A 08-09-95 10:26 Aussie_1.bag
+ * 310992 06-28-94 09:56 INSTALL.EXE
+ * 1 2 3 4
+ * 01234567890123456789012345678901234567890123456789
+ * dirlist from the mirror.pl project, col positions from Mozilla.
+ */
+ p = &(line[toklen[0]]);
+ /* \s(\d\d-\d\d-\d\d)\s+(\d\d:\d\d)\s */
+ if (numtoks >= 4 && toklen[0] <= 18 && isdigit(*tokens[0]) &&
+ (linelen - toklen[0]) >= (53-18) &&
+ p[18-18] == ' ' && p[34-18] == ' ' &&
+ p[37-18] == '-' && p[40-18] == '-' && p[43-18] == ' ' &&
+ p[45-18] == ' ' && p[48-18] == ':' && p[51-18] == ' ' &&
+ isdigit(p[35-18]) && isdigit(p[36-18]) &&
+ isdigit(p[38-18]) && isdigit(p[39-18]) &&
+ isdigit(p[41-18]) && isdigit(p[42-18]) &&
+ isdigit(p[46-18]) && isdigit(p[47-18]) &&
+ isdigit(p[49-18]) && isdigit(p[50-18])
+ )
+ {
+ lstyle = 'O'; /* OS/2 */
+ if (!state->lstyle)
+ {
+ for (pos = 1; lstyle && pos < toklen[0]; pos++)
+ {
+ if (!isdigit(tokens[0][pos]))
+ lstyle = 0;
+ }
+ }
+ }
+
+ if (lstyle == 'O')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(line[toklen[0]]);
+
+ result->fe_cinfs = 1;
+ result->fe_fname = &p[53-18];
+ result->fe_fnlen = (&(line[linelen_sans_wsp]))
+ - (result->fe_fname);
+ result->fe_type = 'f';
+
+ /* I don't have a real listing to determine exact pos, so scan. */
+ for (pos = (18-18); pos < ((35-18)-4); pos++)
+ {
+ if (p[pos+0] == ' ' && p[pos+1] == 'D' &&
+ p[pos+2] == 'I' && p[pos+3] == 'R')
+ {
+ result->fe_type = 'd';
+ break;
+ }
+ }
+
+ if (result->fe_type != 'd')
+ {
+ pos = toklen[0];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[0], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ result->fe_time.tm_mon = atoi(&p[35-18]) - 1;
+ result->fe_time.tm_mday = atoi(&p[38-18]);
+ result->fe_time.tm_year = atoi(&p[41-18]);
+ if (result->fe_time.tm_year < 80)
+ result->fe_time.tm_year += 100;
+ result->fe_time.tm_hour = atoi(&p[46-18]);
+ result->fe_time.tm_min = atoi(&p[49-18]);
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* if (lstyle == 'O') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'O')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_LSL)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'U')) /* /bin/ls & co. */
+ {
+ /* UNIX-style listing, without inum and without blocks
+ * "-rw-r--r-- 1 root other 531 Jan 29 03:26 README"
+ * "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc"
+ * "dr-xr-xr-x 2 root 512 Apr 8 1994 etc"
+ * "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin"
+ * Also produced by Microsoft's FTP servers for Windows:
+ * "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z"
+ * "d--------- 1 owner group 0 May 9 19:45 Softlib"
+ * Also WFTPD for MSDOS:
+ * "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp"
+ * Hellsoft for NetWare:
+ * "d[RWCEMFA] supervisor 512 Jan 16 18:53 login"
+ * "-[RWCEMFA] rhesus 214059 Oct 20 15:27 cx.exe"
+ * Newer Hellsoft for NetWare: (netlab2.usu.edu)
+ * - [RWCEAFMS] NFAUUser 192 Apr 27 15:21 HEADER.html
+ * d [RWCEAFMS] jrd 512 Jul 11 03:01 allupdates
+ * Also NetPresenz for the Mac:
+ * "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit"
+ * "drwxrwxr-x folder 2 May 10 1996 network"
+ * Protected directory:
+ * "drwx-wx-wt 2 root wheel 512 Jul 1 02:15 incoming"
+ * uid/gid instead of username/groupname:
+ * "drwxr-xr-x 2 0 0 512 May 28 22:17 etc"
+ */
+
+ if (numtoks >= 6)
+ {
+ /* there are two perm formats (Hellsoft/NetWare and *IX strmode(3)).
+ * Scan for size column only if the perm format is one or the other.
+ */
+ if (toklen[0] == 1 || (tokens[0][1]) == '[')
+ {
+ if (*tokens[0] == 'd' || *tokens[0] == '-')
+ {
+ pos = toklen[0]-1;
+ p = tokens[0] + 1;
+ if (pos == 0)
+ {
+ p = tokens[1];
+ pos = toklen[1];
+ }
+ if ((pos == 9 || pos == 10) &&
+ (*p == '[' && p[pos-1] == ']') &&
+ (p[1] == 'R' || p[1] == '-') &&
+ (p[2] == 'W' || p[2] == '-') &&
+ (p[3] == 'C' || p[3] == '-') &&
+ (p[4] == 'E' || p[4] == '-'))
+ {
+ /* rest is FMA[S] or AFM[S] */
+ lstyle = 'U'; /* very likely one of the NetWare servers */
+ }
+ }
+ }
+ else if ((toklen[0] == 10 || toklen[0] == 11)
+ && strchr("-bcdlpsw?DFam", *tokens[0]))
+ {
+ p = &(tokens[0][1]);
+ if ((p[0] == 'r' || p[0] == '-') &&
+ (p[1] == 'w' || p[1] == '-') &&
+ (p[3] == 'r' || p[3] == '-') &&
+ (p[4] == 'w' || p[4] == '-') &&
+ (p[6] == 'r' || p[6] == '-') &&
+ (p[7] == 'w' || p[7] == '-'))
+ /* 'x'/p[9] can be S|s|x|-|T|t or implementation specific */
+ {
+ lstyle = 'U'; /* very likely /bin/ls */
+ }
+ }
+ }
+ if (lstyle == 'U') /* first token checks out */
+ {
+ lstyle = 0;
+ for (pos = (numtoks-5); !lstyle && pos > 1; pos--)
+ {
+ /* scan for: (\d+)\s+([A-Z][a-z][a-z])\s+
+ * (\d\d\d\d|\d\:\d\d|\d\d\:\d\d|\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d)
+ * \s+(.+)$
+ */
+ if (isdigit(*tokens[pos]) /* size */
+ /* (\w\w\w) */
+ && toklen[pos+1] == 3 && isalpha(*tokens[pos+1]) &&
+ isalpha(tokens[pos+1][1]) && isalpha(tokens[pos+1][2])
+ /* (\d|\d\d) */
+ && isdigit(*tokens[pos+2]) &&
+ (toklen[pos+2] == 1 ||
+ (toklen[pos+2] == 2 && isdigit(tokens[pos+2][1])))
+ && toklen[pos+3] >= 4 && isdigit(*tokens[pos+3])
+ /* (\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d) */
+ && (toklen[pos+3] <= 5 || (
+ (toklen[pos+3] == 7 || toklen[pos+3] == 8) &&
+ (tokens[pos+3][toklen[pos+3]-3]) == ':'))
+ && isdigit(tokens[pos+3][toklen[pos+3]-2])
+ && isdigit(tokens[pos+3][toklen[pos+3]-1])
+ && (
+ /* (\d\d\d\d) */
+ ((toklen[pos+3] == 4 || toklen[pos+3] == 5) &&
+ isdigit(tokens[pos+3][1]) &&
+ isdigit(tokens[pos+3][2]) )
+ /* (\d\:\d\d|\d\:\d\d\:\d\d) */
+ || ((toklen[pos+3] == 4 || toklen[pos+3] == 7) &&
+ (tokens[pos+3][1]) == ':' &&
+ isdigit(tokens[pos+3][2]) && isdigit(tokens[pos+3][3]))
+ /* (\d\d\:\d\d|\d\d\:\d\d\:\d\d) */
+ || ((toklen[pos+3] == 5 || toklen[pos+3] == 8) &&
+ isdigit(tokens[pos+3][1]) && (tokens[pos+3][2]) == ':' &&
+ isdigit(tokens[pos+3][3]) && isdigit(tokens[pos+3][4]))
+ )
+ )
+ {
+ unsigned int i;
+ lstyle = 'U'; /* assume /bin/ls or variant format */
+ tokmarker = pos;
+
+ /* check that size is numeric */
+ p = tokens[tokmarker];
+ for (i = 0; i < toklen[tokmarker]; i++)
+ {
+ if (!isdigit(*p++))
+ {
+ lstyle = 0;
+ break;
+ }
+ }
+ if (lstyle)
+ {
+ month_num = 0;
+ p = tokens[tokmarker+1];
+ for (i = 0; i < (12*3); i+=3)
+ {
+ if (p[0] == month_names[i+0] &&
+ p[1] == month_names[i+1] &&
+ p[2] == month_names[i+2])
+ break;
+ month_num++;
+ }
+ if (month_num >= 12)
+ lstyle = 0;
+ }
+ } /* relative position test */
+ } /* for (pos = (numtoks-5); !lstyle && pos > 1; pos--) */
+ } /* if (lstyle == 'U') */
+
+ if (lstyle == 'U')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ result->fe_cinfs = 0;
+ result->fe_type = '?';
+ if (*tokens[0] == 'd' || *tokens[0] == 'l')
+ result->fe_type = *tokens[0];
+ else if (*tokens[0] == 'D')
+ result->fe_type = 'd';
+ else if (*tokens[0] == '-' || *tokens[0] == 'F')
+ result->fe_type = 'f'; /* (hopefully a regular file) */
+
+ if (result->fe_type != 'd')
+ {
+ pos = toklen[tokmarker];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[tokmarker], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ result->fe_time.tm_mon = month_num;
+ result->fe_time.tm_mday = atoi(tokens[tokmarker+2]);
+ if (result->fe_time.tm_mday == 0)
+ result->fe_time.tm_mday++;
+
+ p = tokens[tokmarker+3];
+ pos = (unsigned int)atoi(p);
+ if (p[1] == ':') /* one digit hour */
+ p--;
+ if (p[2] != ':') /* year */
+ {
+ result->fe_time.tm_year = pos;
+ }
+ else
+ {
+ result->fe_time.tm_hour = pos;
+ result->fe_time.tm_min = atoi(p+3);
+ if (p[5] == ':')
+ result->fe_time.tm_sec = atoi(p+6);
+
+ if (!state->now_time)
+ {
+ state->now_time = time (NULL);
+ state->now_tm = *localtime (&state->now_time);
+ }
+
+ result->fe_time.tm_year = state->now_tm.tm_year;
+ if ( (( state->now_tm.tm_mon << 5) + state->now_tm.tm_mday) <
+ ((result->fe_time.tm_mon << 5) + result->fe_time.tm_mday) )
+ result->fe_time.tm_year--;
+
+ } /* time/year */
+
+ result->fe_fname = tokens[tokmarker+4];
+ result->fe_fnlen = (&(line[linelen_sans_wsp]))
+ - (result->fe_fname);
+
+ if (result->fe_type == 'l' && result->fe_fnlen > 4)
+ {
+ p = result->fe_fname + 1;
+ for (pos = 1; pos < (result->fe_fnlen - 4); pos++)
+ {
+ if (*p == ' ' && p[1] == '-' && p[2] == '>' && p[3] == ' ')
+ {
+ result->fe_lname = p + 4;
+ result->fe_lnlen = (&(line[linelen_sans_wsp]))
+ - (result->fe_lname);
+ result->fe_fnlen = pos;
+ break;
+ }
+ p++;
+ }
+ }
+
+#if defined(SUPPORT_LSLF) /* some (very rare) servers return ls -lF */
+ if (result->fe_fnlen > 1)
+ {
+ p = result->fe_fname[result->fe_fnlen-1];
+ pos = result->fe_type;
+ if (pos == 'd') {
+ if (*p == '/') result->fe_fnlen--; /* directory */
+ } else if (pos == 'l') {
+ if (*p == '@') result->fe_fnlen--; /* symlink */
+ } else if (pos == 'f') {
+ if (*p == '*') result->fe_fnlen--; /* executable */
+ } else if (*p == '=' || *p == '%' || *p == '|') {
+ result->fe_fnlen--; /* socket, whiteout, fifo */
+ }
+ }
+#endif
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+
+ } /* if (lstyle == 'U') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'U')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_W16) /* 16bit Windows */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'w'))
+ { /* old SuperTCP suite FTP server for Win3.1 */
+ /* old NetManage Chameleon TCP/IP suite FTP server for Win3.1 */
+ /*
+ * SuperTCP dirlist from the mirror.pl project
+ * mon/day/year separator may be '/' or '-'.
+ * . <DIR> 11-16-94 17:16
+ * .. <DIR> 11-16-94 17:16
+ * INSTALL <DIR> 11-16-94 17:17
+ * CMT <DIR> 11-21-94 10:17
+ * DESIGN1.DOC 11264 05-11-95 14:20
+ * README.TXT 1045 05-10-95 11:01
+ * WPKIT1.EXE 960338 06-21-95 17:01
+ * CMT.CSV 0 07-06-95 14:56
+ *
+ * Chameleon dirlist guessed from lynx
+ * . <DIR> Nov 16 1994 17:16
+ * .. <DIR> Nov 16 1994 17:16
+ * INSTALL <DIR> Nov 16 1994 17:17
+ * CMT <DIR> Nov 21 1994 10:17
+ * DESIGN1.DOC 11264 May 11 1995 14:20 A
+ * README.TXT 1045 May 10 1995 11:01
+ * WPKIT1.EXE 960338 Jun 21 1995 17:01 R
+ * CMT.CSV 0 Jul 06 1995 14:56 RHA
+ */
+ if (numtoks >= 4 && toklen[0] < 13 &&
+ ((toklen[1] == 5 && *tokens[1] == '<') || isdigit(*tokens[1])) )
+ {
+ if (numtoks == 4
+ && (toklen[2] == 8 || toklen[2] == 9)
+ && (((tokens[2][2]) == '/' && (tokens[2][5]) == '/') ||
+ ((tokens[2][2]) == '-' && (tokens[2][5]) == '-'))
+ && (toklen[3] == 4 || toklen[3] == 5)
+ && (tokens[3][toklen[3]-3]) == ':'
+ && isdigit(tokens[2][0]) && isdigit(tokens[2][1])
+ && isdigit(tokens[2][3]) && isdigit(tokens[2][4])
+ && isdigit(tokens[2][6]) && isdigit(tokens[2][7])
+ && (toklen[2] < 9 || isdigit(tokens[2][8]))
+ && isdigit(tokens[3][toklen[3]-1]) && isdigit(tokens[3][toklen[3]-2])
+ && isdigit(tokens[3][toklen[3]-4]) && isdigit(*tokens[3])
+ )
+ {
+ lstyle = 'w';
+ }
+ else if ((numtoks == 6 || numtoks == 7)
+ && toklen[2] == 3 && toklen[3] == 2
+ && toklen[4] == 4 && toklen[5] == 5
+ && (tokens[5][2]) == ':'
+ && isalpha(tokens[2][0]) && isalpha(tokens[2][1])
+ && isalpha(tokens[2][2])
+ && isdigit(tokens[3][0]) && isdigit(tokens[3][1])
+ && isdigit(tokens[4][0]) && isdigit(tokens[4][1])
+ && isdigit(tokens[4][2]) && isdigit(tokens[4][3])
+ && isdigit(tokens[5][0]) && isdigit(tokens[5][1])
+ && isdigit(tokens[5][3]) && isdigit(tokens[5][4])
+ /* could also check that (&(tokens[5][5]) - tokens[2]) == 17 */
+ )
+ {
+ lstyle = 'w';
+ }
+ if (lstyle && state->lstyle != lstyle) /* first time */
+ {
+ p = tokens[1];
+ if (toklen[1] != 5 || p[0] != '<' || p[1] != 'D' ||
+ p[2] != 'I' || p[3] != 'R' || p[4] != '>')
+ {
+ for (pos = 0; lstyle && pos < toklen[1]; pos++)
+ {
+ if (!isdigit(*p++))
+ lstyle = 0;
+ }
+ } /* not <DIR> */
+ } /* if (first time) */
+ } /* if (numtoks == ...) */
+
+ if (lstyle == 'w')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = toklen[0];
+ result->fe_type = 'd';
+
+ p = tokens[1];
+ if (isdigit(*p))
+ {
+ result->fe_type = 'f';
+ pos = toklen[1];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, p, pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ p = tokens[2];
+ if (toklen[2] == 3) /* Chameleon */
+ {
+ tbuf[0] = toupper(p[0]);
+ tbuf[1] = tolower(p[1]);
+ tbuf[2] = tolower(p[2]);
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (tbuf[0] == month_names[pos+0] &&
+ tbuf[1] == month_names[pos+1] &&
+ tbuf[2] == month_names[pos+2])
+ {
+ result->fe_time.tm_mon = pos/3;
+ result->fe_time.tm_mday = atoi(tokens[3]);
+ result->fe_time.tm_year = atoi(tokens[4]) - 1900;
+ break;
+ }
+ }
+ pos = 5; /* Chameleon toknum of date field */
+ }
+ else
+ {
+ result->fe_time.tm_mon = atoi(p+0)-1;
+ result->fe_time.tm_mday = atoi(p+3);
+ result->fe_time.tm_year = atoi(p+6);
+ if (result->fe_time.tm_year < 80) /* SuperTCP */
+ result->fe_time.tm_year += 100;
+
+ pos = 3; /* SuperTCP toknum of date field */
+ }
+
+ result->fe_time.tm_hour = atoi(tokens[pos]);
+ result->fe_time.tm_min = atoi(&(tokens[pos][toklen[pos]-2]));
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* (lstyle == 'w') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'w')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_DLS) /* dls -dtR */
+ if (!lstyle &&
+ (state->lstyle == 'D' || (!state->lstyle && state->numlines == 1)))
+ /* /bin/dls lines have to be immediately recognizable (first line) */
+ {
+ /* I haven't seen an FTP server that delivers a /bin/dls listing,
+ * but can infer the format from the lynx and mirror.pl projects.
+ * Both formats are supported.
+ *
+ * Lynx says:
+ * README 763 Information about this server\0
+ * bin/ - \0
+ * etc/ = \0
+ * ls-lR 0 \0
+ * ls-lR.Z 3 \0
+ * pub/ = Public area\0
+ * usr/ - \0
+ * morgan 14 -> ../real/morgan\0
+ * TIMIT.mostlikely.Z\0
+ * 79215 \0
+ *
+ * mirror.pl says:
+ * filename: ^(\S*)\s+
+ * size: (\-|\=|\d+)\s+
+ * month/day: ((\w\w\w\s+\d+|\d+\s+\w\w\w)\s+
+ * time/year: (\d+:\d+|\d\d\d\d))\s+
+ * rest: (.+)
+ *
+ * README 763 Jul 11 21:05 Information about this server
+ * bin/ - Apr 28 1994
+ * etc/ = 11 Jul 21:04
+ * ls-lR 0 6 Aug 17:14
+ * ls-lR.Z 3 05 Sep 1994
+ * pub/ = Jul 11 21:04 Public area
+ * usr/ - Sep 7 09:39
+ * morgan 14 Apr 18 09:39 -> ../real/morgan
+ * TIMIT.mostlikely.Z
+ * 79215 Jul 11 21:04
+ */
+ if (!state->lstyle && line[linelen-1] == ':' &&
+ linelen >= 2 && toklen[numtoks-1] != 1)
+ {
+ /* code in mirror.pl suggests that a listing may be preceded
+ * by a PWD line in the form "/some/dir/names/here:"
+ * but does not necessarily begin with '/'. *sigh*
+ */
+ pos = 0;
+ p = line;
+ while (pos < (linelen-1))
+ {
+ /* illegal (or extremely unusual) chars in a dirspec */
+ if (*p == '<' || *p == '|' || *p == '>' ||
+ *p == '?' || *p == '*' || *p == '\\')
+ break;
+ if (*p == '/' && pos < (linelen-2) && p[1] == '/')
+ break;
+ pos++;
+ p++;
+ }
+ if (pos == (linelen-1))
+ {
+ state->lstyle = 'D';
+ return '?';
+ }
+ }
+
+ if (!lstyle && numtoks >= 2)
+ {
+ pos = 22; /* pos of (\d+|-|=) if this is not part of a multiline */
+ if (state->lstyle && carry_buf_len) /* first is from previous line */
+ pos = toklen[1]-1; /* and is 'as-is' (may contain whitespace) */
+
+ if (linelen > pos)
+ {
+ p = &line[pos];
+ if ((*p == '-' || *p == '=' || isdigit(*p)) &&
+ ((linelen == (pos+1)) ||
+ (linelen >= (pos+3) && p[1] == ' ' && p[2] == ' ')) )
+ {
+ tokmarker = 1;
+ if (!carry_buf_len)
+ {
+ pos = 1;
+ while (pos < numtoks && (tokens[pos]+toklen[pos]) < (&line[23]))
+ pos++;
+ tokmarker = 0;
+ if ((tokens[pos]+toklen[pos]) == (&line[23]))
+ tokmarker = pos;
+ }
+ if (tokmarker)
+ {
+ lstyle = 'D';
+ if (*tokens[tokmarker] == '-' || *tokens[tokmarker] == '=')
+ {
+ if (toklen[tokmarker] != 1 ||
+ (tokens[tokmarker-1][toklen[tokmarker-1]-1]) != '/')
+ lstyle = 0;
+ }
+ else
+ {
+ for (pos = 0; lstyle && pos < toklen[tokmarker]; pos++)
+ {
+ if (!isdigit(tokens[tokmarker][pos]))
+ lstyle = 0;
+ }
+ }
+ if (lstyle && !state->lstyle) /* first time */
+ {
+ /* scan for illegal (or incredibly unusual) chars in fname */
+ for (p = tokens[0]; lstyle &&
+ p < &(tokens[tokmarker-1][toklen[tokmarker-1]]); p++)
+ {
+ if (*p == '<' || *p == '|' || *p == '>' ||
+ *p == '?' || *p == '*' || *p == '/' || *p == '\\')
+ lstyle = 0;
+ }
+ }
+
+ } /* size token found */
+ } /* expected chars behind expected size token */
+ } /* if (linelen > pos) */
+ } /* if (!lstyle && numtoks >= 2) */
+
+ if (!lstyle && state->lstyle == 'D' && !carry_buf_len)
+ {
+ /* the filename of a multi-line entry can be identified
+ * correctly only if dls format had been previously established.
+ * This should always be true because there should be entries
+ * for '.' and/or '..' and/or CWD that precede the rest of the
+ * listing.
+ */
+ pos = linelen;
+ if (pos > (sizeof(state->carry_buf)-1))
+ pos = sizeof(state->carry_buf)-1;
+ memcpy( state->carry_buf, line, pos );
+ state->carry_buf_len = pos;
+ return '?';
+ }
+
+ if (lstyle == 'D')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(tokens[tokmarker-1][toklen[tokmarker-1]]);
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = p - tokens[0];
+ result->fe_type = 'f';
+
+ if (result->fe_fname[result->fe_fnlen-1] == '/')
+ {
+ if (result->fe_lnlen == 1)
+ result->fe_type = '?';
+ else
+ {
+ result->fe_fnlen--;
+ result->fe_type = 'd';
+ }
+ }
+ else if (isdigit(*tokens[tokmarker]))
+ {
+ pos = toklen[tokmarker];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, tokens[tokmarker], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ if ((tokmarker+3) < numtoks &&
+ (&(tokens[numtoks-1][toklen[numtoks-1]]) -
+ tokens[tokmarker+1]) >= (1+1+3+1+4) )
+ {
+ pos = (tokmarker+3);
+ p = tokens[pos];
+ pos = toklen[pos];
+
+ if ((pos == 4 || pos == 5)
+ && isdigit(*p) && isdigit(p[pos-1]) && isdigit(p[pos-2])
+ && ((pos == 5 && p[2] == ':') ||
+ (pos == 4 && (isdigit(p[1]) || p[1] == ':')))
+ )
+ {
+ month_num = tokmarker+1; /* assumed position of month field */
+ pos = tokmarker+2; /* assumed position of mday field */
+ if (isdigit(*tokens[month_num])) /* positions are reversed */
+ {
+ month_num++;
+ pos--;
+ }
+ p = tokens[month_num];
+ if (isdigit(*tokens[pos])
+ && (toklen[pos] == 1 ||
+ (toklen[pos] == 2 && isdigit(tokens[pos][1])))
+ && toklen[month_num] == 3
+ && isalpha(*p) && isalpha(p[1]) && isalpha(p[2]) )
+ {
+ pos = atoi(tokens[pos]);
+ if (pos > 0 && pos <= 31)
+ {
+ result->fe_time.tm_mday = pos;
+ month_num = 1;
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (p[0] == month_names[pos+0] &&
+ p[1] == month_names[pos+1] &&
+ p[2] == month_names[pos+2])
+ break;
+ month_num++;
+ }
+ if (month_num > 12)
+ result->fe_time.tm_mday = 0;
+ else
+ result->fe_time.tm_mon = month_num - 1;
+ }
+ }
+ if (result->fe_time.tm_mday)
+ {
+ tokmarker += 3; /* skip mday/mon/yrtime (to find " -> ") */
+ p = tokens[tokmarker];
+
+ pos = atoi(p);
+ if (pos > 24)
+ result->fe_time.tm_year = pos-1900;
+ else
+ {
+ if (p[1] == ':')
+ p--;
+ result->fe_time.tm_hour = pos;
+ result->fe_time.tm_min = atoi(p+3);
+ if (!state->now_time)
+ {
+ state->now_time = time (NULL);
+ state->now_tm = *localtime (&state->now_time);
+ }
+ result->fe_time.tm_year = state->now_tm.tm_year;
+ if ( (( state->now_tm.tm_mon << 4) + state->now_tm.tm_mday) <
+ ((result->fe_time.tm_mon << 4) + result->fe_time.tm_mday) )
+ result->fe_time.tm_year--;
+ } /* got year or time */
+ } /* got month/mday */
+ } /* may have year or time */
+ } /* enough remaining to possibly have date/time */
+
+ if (numtoks > (tokmarker+2))
+ {
+ pos = tokmarker+1;
+ p = tokens[pos];
+ if (toklen[pos] == 2 && *p == '-' && p[1] == '>')
+ {
+ p = &(tokens[numtoks-1][toklen[numtoks-1]]);
+ result->fe_type = 'l';
+ result->fe_lname = tokens[pos+1];
+ result->fe_lnlen = p - result->fe_lname;
+ if (result->fe_lnlen > 1 &&
+ result->fe_lname[result->fe_lnlen-1] == '/')
+ result->fe_lnlen--;
+ }
+ } /* if (numtoks > (tokmarker+2)) */
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+
+ } /* if (lstyle == 'D') */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'D')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+ } /* if (linelen > 0) */
+
+ if (state->parsed_one || state->lstyle) /* junk if we fail to parse */
+ return '?'; /* this time but had previously parsed successfully */
+ return '"'; /* its part of a comment or error message */
+}
+
+/* ==================================================================== */
+/* standalone testing */
+/* ==================================================================== */
+#if 0
+
+#include <stdio.h>
+
+static int do_it(FILE *outfile,
+ char *line, size_t linelen, struct list_state *state,
+ char **cmnt_buf, unsigned int *cmnt_buf_sz,
+ char **list_buf, unsigned int *list_buf_sz )
+{
+ struct list_result result;
+ char *p;
+ int rc;
+
+ rc = ParseFTPLIST( line, state, &result );
+
+ if (!outfile)
+ {
+ outfile = stdout;
+ if (rc == '?')
+ fprintf(outfile, "junk: %.*s\n", (int)linelen, line );
+ else if (rc == '"')
+ fprintf(outfile, "cmnt: %.*s\n", (int)linelen, line );
+ else
+ fprintf(outfile,
+ "list: %02u-%02u-%02u %02u:%02u%cM %20s %.*s%s%.*s\n",
+ (result.fe_time.tm_mday ? (result.fe_time.tm_mon + 1) : 0),
+ result.fe_time.tm_mday,
+ (result.fe_time.tm_mday ? (result.fe_time.tm_year % 100) : 0),
+ result.fe_time.tm_hour -
+ ((result.fe_time.tm_hour > 12)?(12):(0)),
+ result.fe_time.tm_min,
+ ((result.fe_time.tm_hour >= 12) ? 'P' : 'A'),
+ (rc == 'd' ? "<DIR> " :
+ (rc == 'l' ? "<JUNCTION> " : result.fe_size)),
+ (int)result.fe_fnlen, result.fe_fname,
+ ((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
+ (int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
+ ((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
+ }
+ else if (rc != '?') /* NOT junk */
+ {
+ char **bufp = list_buf;
+ unsigned int *bufz = list_buf_sz;
+
+ if (rc == '"') /* comment - make it a 'result' */
+ {
+ memset( &result, 0, sizeof(result));
+ result.fe_fname = line;
+ result.fe_fnlen = linelen;
+ result.fe_type = 'f';
+ if (line[linelen-1] == '/')
+ {
+ result.fe_type = 'd';
+ result.fe_fnlen--;
+ }
+ bufp = cmnt_buf;
+ bufz = cmnt_buf_sz;
+ rc = result.fe_type;
+ }
+
+ linelen = 80 + result.fe_fnlen + result.fe_lnlen;
+ p = (char *)realloc( *bufp, *bufz + linelen );
+ if (!p)
+ return -1;
+ sprintf( &p[*bufz],
+ "%02u-%02u-%04u %02u:%02u:%02u %20s %.*s%s%.*s\n",
+ (result.fe_time.tm_mday ? (result.fe_time.tm_mon + 1) : 0),
+ result.fe_time.tm_mday,
+ (result.fe_time.tm_mday ? (result.fe_time.tm_year + 1900) : 0),
+ result.fe_time.tm_hour,
+ result.fe_time.tm_min,
+ result.fe_time.tm_sec,
+ (rc == 'd' ? "<DIR> " :
+ (rc == 'l' ? "<JUNCTION> " : result.fe_size)),
+ (int)result.fe_fnlen, result.fe_fname,
+ ((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
+ (int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
+ ((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
+ linelen = strlen(&p[*bufz]);
+ *bufp = p;
+ *bufz = *bufz + linelen;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *infile = (FILE *)0;
+ FILE *outfile = (FILE *)0;
+ int need_close_in = 0;
+ int need_close_out = 0;
+
+ if (argc > 1)
+ {
+ infile = stdin;
+ if (strcmp(argv[1], "-") == 0)
+ need_close_in = 0;
+ else if ((infile = fopen(argv[1], "r")) != ((FILE *)0))
+ need_close_in = 1;
+ else
+ fprintf(stderr, "Unable to open input file '%s'\n", argv[1]);
+ }
+ if (infile && argc > 2)
+ {
+ outfile = stdout;
+ if (strcmp(argv[2], "-") == 0)
+ need_close_out = 0;
+ else if ((outfile = fopen(argv[2], "w")) != ((FILE *)0))
+ need_close_out = 1;
+ else
+ {
+ fprintf(stderr, "Unable to open output file '%s'\n", argv[2]);
+ fclose(infile);
+ infile = (FILE *)0;
+ }
+ }
+
+ if (!infile)
+ {
+ char *appname = &(argv[0][strlen(argv[0])]);
+ while (appname > argv[0])
+ {
+ appname--;
+ if (*appname == '/' || *appname == '\\' || *appname == ':')
+ {
+ appname++;
+ break;
+ }
+ }
+ fprintf(stderr,
+ "Usage: %s <inputfilename> [<outputfilename>]\n"
+ "\nIf an outout file is specified the results will be"
+ "\nbe post-processed, and only the file entries will appear"
+ "\n(or all comments if there are no file entries)."
+ "\nNot specifying an output file causes %s to run in \"debug\""
+ "\nmode, ie results are printed as lines are parsed."
+ "\nIf a filename is a single dash ('-'), stdin/stdout is used."
+ "\n", appname, appname );
+ }
+ else
+ {
+ char *cmnt_buf = (char *)0;
+ unsigned int cmnt_buf_sz = 0;
+ char *list_buf = (char *)0;
+ unsigned int list_buf_sz = 0;
+
+ struct list_state state;
+ char line[512];
+
+ memset( &state, 0, sizeof(state) );
+ while (fgets(line, sizeof(line), infile))
+ {
+ size_t linelen = strlen(line);
+ if (linelen < (sizeof(line)-1))
+ {
+ if (linelen > 0 && line[linelen-1] == '\n')
+ linelen--;
+ if (do_it( outfile, line, linelen, &state,
+ &cmnt_buf, &cmnt_buf_sz, &list_buf, &list_buf_sz) != 0)
+ {
+ fprintf(stderr, "Insufficient memory. Listing may be incomplete.\n");
+ break;
+ }
+ }
+ else
+ {
+ /* no '\n' found. drop this and everything up to the next '\n' */
+ fprintf(stderr, "drop: %.*s", (int)linelen, line );
+ while (linelen == sizeof(line))
+ {
+ if (!fgets(line, sizeof(line), infile))
+ break;
+ linelen = 0;
+ while (linelen < sizeof(line) && line[linelen] != '\n')
+ linelen++;
+ fprintf(stderr, "%.*s", (int)linelen, line );
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ if (outfile)
+ {
+ if (list_buf)
+ fwrite( list_buf, 1, list_buf_sz, outfile );
+ else if (cmnt_buf)
+ fwrite( cmnt_buf, 1, cmnt_buf_sz, outfile );
+ }
+ if (list_buf)
+ free(list_buf);
+ if (cmnt_buf)
+ free(cmnt_buf);
+
+ if (need_close_in)
+ fclose(infile);
+ if (outfile && need_close_out)
+ fclose(outfile);
+ }
+
+ return 0;
+}
+#endif
diff --git a/trunk/daemon/ParseFTPList.h b/trunk/daemon/ParseFTPList.h
new file mode 100644
index 00000000..5580657e
--- /dev/null
+++ b/trunk/daemon/ParseFTPList.h
@@ -0,0 +1,127 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Cyrus Patel <cyp@fb14.uni-mainz.de>.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <glib.h>
+
+/* ParseFTPList() parses lines from an FTP LIST command.
+**
+** Written July 2002 by Cyrus Patel <cyp@fb14.uni-mainz.de>
+** with acknowledgements to squid, lynx, wget and ftpmirror.
+**
+** Arguments:
+** 'line': line of FTP data connection output. The line is assumed
+** to end at the first '\0' or '\n' or '\r\n'.
+** 'state': a structure used internally to track state between
+** lines. Needs to be bzero()'d at LIST begin.
+** 'result': where ParseFTPList will store the results of the parse
+** if 'line' is not a comment and is not junk.
+**
+** Returns one of the following:
+** 'd' - LIST line is a directory entry ('result' is valid)
+** 'f' - LIST line is a file's entry ('result' is valid)
+** 'l' - LIST line is a symlink's entry ('result' is valid)
+** '?' - LIST line is junk. (cwd, non-file/dir/link, etc)
+** '"' - its not a LIST line (its a "comment")
+**
+** It may be advisable to let the end-user see "comments" (particularly when
+** the listing results in ONLY such lines) because such a listing may be:
+** - an unknown LIST format (NLST or "custom" format for example)
+** - an error msg (EPERM,ENOENT,ENFILE,EMFILE,ENOTDIR,ENOTBLK,EEXDEV etc).
+** - an empty directory and the 'comment' is a "total 0" line or similar.
+** (warning: a "total 0" can also mean the total size is unknown).
+**
+** ParseFTPList() supports all known FTP LISTing formats:
+** - '/bin/ls -l' and all variants (including Hellsoft FTP for NetWare);
+** - EPLF (Easily Parsable List Format);
+** - Windows NT's default "DOS-dirstyle";
+** - OS/2 basic server format LIST format;
+** - VMS (MultiNet, UCX, and CMU) LIST format (including multi-line format);
+** - IBM VM/CMS, VM/ESA LIST format (two known variants);
+** - SuperTCP FTP Server for Win16 LIST format;
+** - NetManage Chameleon (NEWT) for Win16 LIST format;
+** - '/bin/dls' (two known variants, plus multi-line) LIST format;
+** If there are others, then I'd like to hear about them (send me a sample).
+**
+** NLSTings are not supported explicitely because they cannot be machine
+** parsed consistently: NLSTings do not have unique characteristics - even
+** the assumption that there won't be whitespace on the line does not hold
+** because some nlistings have more than one filename per line and/or
+** may have filenames that have spaces in them. Moreover, distinguishing
+** between an error message and an NLST line would require ParseList() to
+** recognize all the possible strerror() messages in the world.
+*/
+
+
+/* #undef anything you don't want to support */
+#define SUPPORT_LSL /* /bin/ls -l and dozens of variations therof */
+#define SUPPORT_DLS /* /bin/dls format (very, Very, VERY rare) */
+#define SUPPORT_EPLF /* Extraordinarily Pathetic List Format */
+#define SUPPORT_DOS /* WinNT server in 'site dirstyle' dos */
+#define SUPPORT_VMS /* VMS (all: MultiNet, UCX, CMU-IP) */
+#define SUPPORT_CMS /* IBM VM/CMS,VM/ESA (z/VM and LISTING forms) */
+#define SUPPORT_OS2 /* IBM TCP/IP for OS/2 - FTP Server */
+#define SUPPORT_W16 /* win16 hosts: SuperTCP or NetManage Chameleon */
+
+struct list_state
+{
+ void *magic; /* to determine if previously initialized */
+ time_t now_time; /* current date for year calculation */
+ struct tm now_tm; /* current date for year calculation */
+ gint32 lstyle; /* LISTing style */
+ gint32 parsed_one; /* returned anything yet? */
+ char carry_buf[84]; /* for VMS multiline */
+ guint32 carry_buf_len; /* length of name in carry_buf */
+ guint32 numlines; /* number of lines seen */
+};
+
+struct list_result
+{
+ gint32 fe_type; /* 'd'(dir) or 'l'(link) or 'f'(file) */
+ const char * fe_fname; /* pointer to filename */
+ guint32 fe_fnlen; /* length of filename */
+ const char * fe_lname; /* pointer to symlink name */
+ guint32 fe_lnlen; /* length of symlink name */
+ char fe_size[40]; /* size of file in bytes (<= (2^128 - 1)) */
+ struct tm fe_time; /* last-modified time */
+ gint32 fe_cinfs; /* file system is definitely case insensitive */
+ /* (converting all-upcase names may be desirable) */
+};
+
+int ParseFTPList(const char *line,
+ struct list_state *state,
+ struct list_result *result );
+
diff --git a/trunk/daemon/archive.mount.in b/trunk/daemon/archive.mount.in
new file mode 100644
index 00000000..4c3237bd
--- /dev/null
+++ b/trunk/daemon/archive.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=archive
+Exec=@libexecdir@/gvfsd-archive
+AutoMount=false
+Scheme=archive
diff --git a/trunk/daemon/burn.mount.in b/trunk/daemon/burn.mount.in
new file mode 100644
index 00000000..ef4fd798
--- /dev/null
+++ b/trunk/daemon/burn.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=burn
+Exec=@libexecdir@/gvfsd-burn
+AutoMount=true
+
diff --git a/trunk/daemon/cdda.mount.in b/trunk/daemon/cdda.mount.in
new file mode 100644
index 00000000..8541c208
--- /dev/null
+++ b/trunk/daemon/cdda.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=cdda
+Exec=@libexecdir@/gvfsd-cdda
+AutoMount=false
diff --git a/trunk/daemon/computer.mount.in b/trunk/daemon/computer.mount.in
new file mode 100644
index 00000000..c021644b
--- /dev/null
+++ b/trunk/daemon/computer.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=computer
+Exec=@libexecdir@/gvfsd-computer
+AutoMount=true
+
diff --git a/trunk/daemon/daemon-main-generic.c b/trunk/daemon/daemon-main-generic.c
new file mode 100644
index 00000000..3de0133b
--- /dev/null
+++ b/trunk/daemon/daemon-main-generic.c
@@ -0,0 +1,59 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "daemon-main.h"
+#include G_STRINGIFY(BACKEND_HEADER)
+
+int
+main (int argc, char *argv[])
+{
+ daemon_init ();
+#ifdef BACKEND_SETUP_FUNC
+ BACKEND_SETUP_FUNC ();
+#else
+ daemon_setup ();
+#endif
+ daemon_main (argc, argv,
+#ifdef MAX_JOB_THREADS
+ MAX_JOB_THREADS,
+#else
+ -1,
+#endif
+#ifdef DEFAULT_BACKEND_TYPE
+ G_STRINGIFY(DEFAULT_BACKEND_TYPE),
+#else
+ NULL,
+#endif
+#ifdef MOUNTABLE_DBUS_NAME
+ G_STRINGIFY(MOUNTABLE_DBUS_NAME),
+#else
+ NULL,
+#endif
+ BACKEND_TYPES
+ NULL);
+
+ return 0;
+}
diff --git a/trunk/daemon/daemon-main.c b/trunk/daemon/daemon-main.c
new file mode 100644
index 00000000..22cebe60
--- /dev/null
+++ b/trunk/daemon/daemon-main.c
@@ -0,0 +1,296 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include "daemon-main.h"
+#include <glib/gi18n.h>
+#include <gvfsdaemon.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsbackend.h>
+
+static char *spawner_id = NULL;
+static char *spawner_path = NULL;
+
+static gboolean print_debug = FALSE;
+
+static void
+log_debug (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer unused_data)
+{
+ if (print_debug)
+ g_print ("%s", message);
+}
+
+void
+daemon_init (void)
+{
+ DBusConnection *connection;
+ DBusError derror;
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ dbus_threads_init_default ();
+ g_thread_init (NULL);
+ g_type_init ();
+
+ g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, log_debug, NULL);
+
+
+ dbus_error_init (&derror);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ if (connection == NULL)
+ {
+ g_printerr (_("Error connecting to D-Bus: %s"), derror.message);
+ g_printerr ("\n");
+ dbus_error_free (&derror);
+ exit (1);
+ }
+}
+
+void
+daemon_setup (void)
+{
+ char *name, *up;
+
+ up = g_ascii_strup (G_STRINGIFY (DEFAULT_BACKEND_TYPE), -1);
+ /* translators: This is the default daemon's application name,
+ * the %s is the type of the backend, like "ftp" */
+ name = g_strdup_printf (_("%s Filesystem Service"), up);
+ g_set_application_name (name);
+ g_free (name);
+ g_free (up);
+}
+
+static void
+send_spawned (DBusConnection *connection, gboolean succeeded, char *error_message)
+{
+ DBusMessage *message;
+ dbus_bool_t dbus_succeeded;
+
+ if (error_message == NULL)
+ error_message = "";
+
+ if (spawner_id == NULL || spawner_path == NULL)
+ {
+ if (!succeeded)
+ {
+ g_printerr (_("Error: %s"), error_message);
+ g_printerr ("\n");
+ }
+ return;
+ }
+
+ message = dbus_message_new_method_call (spawner_id,
+ spawner_path,
+ G_VFS_DBUS_SPAWNER_INTERFACE,
+ G_VFS_DBUS_OP_SPAWNED);
+ dbus_message_set_no_reply (message, TRUE);
+
+ dbus_succeeded = succeeded;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_BOOLEAN, &dbus_succeeded,
+ DBUS_TYPE_STRING, &error_message,
+ DBUS_TYPE_INVALID))
+ _g_dbus_oom ();
+
+ dbus_connection_send (connection, message, NULL);
+ /* Make sure the message is sent */
+ dbus_connection_flush (connection);
+}
+
+GMountSpec *
+daemon_parse_args (int argc, char *argv[], const char *default_type)
+{
+ GMountSpec *mount_spec;
+
+ if (argc > 1 && strcmp (argv[1], "--debug") == 0)
+ {
+ print_debug = TRUE;
+ argc--;
+ argv++;
+ }
+ else if (g_getenv ("GVFS_DEBUG"))
+ {
+ print_debug = TRUE;
+ }
+
+ mount_spec = NULL;
+ if (argc > 1 && strcmp (argv[1], "--spawner") == 0)
+ {
+ if (argc < 4)
+ {
+ g_printerr (_("Usage: %s --spawner dbus-id object_path"), argv[0]);
+ g_printerr ("\n");
+ exit (1);
+ }
+
+ spawner_id = argv[2];
+ spawner_path = argv[3];
+ }
+ else if (argc > 1 || default_type != NULL)
+ {
+ gboolean found_type;
+ int i;
+
+ mount_spec = g_mount_spec_new (default_type);
+ found_type = default_type != NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ char *p;
+ char *key;
+
+ p = strchr (argv[i], '=');
+ if (p == NULL || p[1] == 0 || p == argv[i])
+ {
+ g_printerr (_("Usage: %s key=value key=value ..."), argv[0]);
+ g_printerr ("\n");
+ exit (1);
+ }
+
+ key = g_strndup (argv[i], p - argv[i]);
+ if (strcmp (key, "type") == 0)
+ found_type = TRUE;
+
+ g_mount_spec_set (mount_spec, key, p+1);
+ g_debug ("setting '%s' to '%s'\n", key, p+1);
+ g_free (key);
+ }
+
+ if (!found_type)
+ {
+ g_printerr (_("No mount type specified"));
+ g_printerr ("\n");
+ g_printerr (_("Usage: %s key=value key=value ..."), argv[0]);
+ g_printerr ("\n");
+ exit (1);
+ }
+ }
+
+ return mount_spec;
+}
+
+void
+daemon_main (int argc,
+ char *argv[],
+ int max_job_threads,
+ const char *default_type,
+ const char *mountable_name,
+ const char *first_type_name,
+ ...)
+{
+ va_list var_args;
+ DBusConnection *connection;
+ GMainLoop *loop;
+ GVfsDaemon *daemon;
+ DBusError derror;
+ GMountSpec *mount_spec;
+ GMountSource *mount_source;
+ GError *error;
+ int res;
+ const char *type;
+
+ dbus_error_init (&derror);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ if (connection == NULL)
+ {
+ g_printerr (_("Error connecting to D-Bus: %s"), derror.message);
+ g_printerr ("\n");
+ dbus_error_free (&derror);
+ exit (1);
+ }
+
+ mount_spec = daemon_parse_args (argc, argv, default_type);
+
+ va_start (var_args, first_type_name);
+
+ type = first_type_name;
+
+ while (type != NULL)
+ {
+ GType backend_type = va_arg (var_args, GType);
+
+ g_vfs_register_backend (backend_type, type);
+
+ type = va_arg (var_args, char *);
+ }
+
+ error = NULL;
+ if (mountable_name)
+ {
+
+ res = dbus_bus_request_name (connection,
+ mountable_name,
+ 0, &derror);
+
+ if (res != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ if (res == -1)
+ _g_error_from_dbus (&derror, &error);
+ else
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("mountpoint for %s already running"), mountable_name);
+
+ send_spawned (connection, FALSE, error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ }
+
+ daemon = g_vfs_daemon_new (FALSE, FALSE);
+ if (daemon == NULL)
+ {
+ send_spawned (connection, FALSE, _("error starting mount daemon"));
+ exit (1);
+ }
+
+ g_vfs_daemon_set_max_threads (daemon, max_job_threads);
+
+ send_spawned (connection, TRUE, NULL);
+
+ if (mount_spec)
+ {
+ mount_source = g_mount_source_new_dummy ();
+ g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, FALSE, NULL);
+ g_mount_spec_unref (mount_spec);
+ g_object_unref (mount_source);
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (loop);
+}
+
diff --git a/trunk/daemon/daemon-main.h b/trunk/daemon/daemon-main.h
new file mode 100644
index 00000000..818940a5
--- /dev/null
+++ b/trunk/daemon/daemon-main.h
@@ -0,0 +1,45 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __MAIN_HELPER_H__
+#define __MAIN_HELPER_H__
+
+#include "gmountsource.h"
+
+G_BEGIN_DECLS
+
+void daemon_init (void);
+GMountSpec *daemon_parse_args (int argc,
+ char *argv[],
+ const char *default_type);
+void daemon_setup (void);
+void daemon_main (int argc,
+ char *argv[],
+ int max_job_threads,
+ const char *default_type,
+ const char *mountable_name,
+ const char *first_type_name,
+ ...);
+
+G_END_DECLS
+
+#endif /* __MAIN_HELPER__ */
diff --git a/trunk/daemon/dav+sd.mount.in b/trunk/daemon/dav+sd.mount.in
new file mode 100644
index 00000000..45703270
--- /dev/null
+++ b/trunk/daemon/dav+sd.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=dav+sd;davs+sd
+Exec=@libexecdir@/gvfsd-dav
+AutoMount=false
diff --git a/trunk/daemon/dav.mount.in b/trunk/daemon/dav.mount.in
new file mode 100644
index 00000000..6324625c
--- /dev/null
+++ b/trunk/daemon/dav.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=dav;davs
+Exec=@libexecdir@/gvfsd-dav
+AutoMount=false
diff --git a/trunk/daemon/dbus-gmain.c b/trunk/daemon/dbus-gmain.c
new file mode 100644
index 00000000..06f03682
--- /dev/null
+++ b/trunk/daemon/dbus-gmain.c
@@ -0,0 +1,717 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/* dbus-gmain.c GLib main loop integration
+ *
+ * Copyright (C) 2002, 2003 CodeFactory AB
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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 <config.h>
+#include <string.h>
+#include "dbus-gmain.h"
+
+#include <libintl.h>
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+
+/**
+ * @defgroup DBusGLib GLib bindings
+ * @brief API for using D-BUS with GLib
+ *
+ * libdbus proper is a low-level API, these GLib bindings wrap libdbus
+ * with a much higher-level approach. The higher level approach is
+ * possible because GLib defines a main loop, an object/type system,
+ * and an out-of-memory handling policy (it exits the program).
+ * See http://www.gtk.org for GLib information.
+ *
+ * To manipulate remote objects, use #DBusGProxy.
+ */
+
+/**
+ * @defgroup DBusGLibInternals GLib bindings implementation details
+ * @ingroup DBusInternals
+ * @brief Implementation details of GLib bindings
+ *
+ * @{
+ */
+
+/**
+ * A GSource subclass for dispatching DBusConnection messages.
+ * We need this on top of the IO handlers, because sometimes
+ * there are messages to dispatch queued up but no IO pending.
+ */
+typedef struct
+{
+ GSource source; /**< the parent GSource */
+ DBusConnection *connection; /**< the connection to dispatch */
+} DBusGMessageQueue;
+
+static gboolean message_queue_prepare (GSource *source,
+ gint *timeout);
+static gboolean message_queue_check (GSource *source);
+static gboolean message_queue_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data);
+
+static const GSourceFuncs message_queue_funcs = {
+ message_queue_prepare,
+ message_queue_check,
+ message_queue_dispatch,
+ NULL
+};
+
+static gboolean
+message_queue_prepare (GSource *source,
+ gint *timeout)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+ *timeout = -1;
+
+ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+message_queue_check (GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean
+message_queue_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+ dbus_connection_ref (connection);
+
+ /* Only dispatch once - we don't want to starve other GSource */
+ dbus_connection_dispatch (connection);
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+typedef struct
+{
+ GMainContext *context; /**< the main context */
+ GSList *ios; /**< all IOHandler */
+ GSList *timeouts; /**< all TimeoutHandler */
+ DBusConnection *connection; /**< NULL if this is really for a server not a connection */
+ GSource *message_queue_source; /**< DBusGMessageQueue */
+} ConnectionSetup;
+
+
+typedef struct
+{
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+ ConnectionSetup *cs;
+ GSource *source;
+ DBusTimeout *timeout;
+} TimeoutHandler;
+
+static dbus_int32_t connection_slot = -1;
+static dbus_int32_t server_slot = -1;
+
+static ConnectionSetup*
+connection_setup_new (GMainContext *context,
+ DBusConnection *connection)
+{
+ ConnectionSetup *cs;
+
+ cs = g_new0 (ConnectionSetup, 1);
+
+ g_assert (context != NULL);
+
+ cs->context = context;
+ g_main_context_ref (cs->context);
+
+ if (connection)
+ {
+ cs->connection = connection;
+
+ cs->message_queue_source = g_source_new ((GSourceFuncs*)&message_queue_funcs,
+ sizeof (DBusGMessageQueue));
+ ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
+ g_source_attach (cs->message_queue_source, cs->context);
+ }
+
+ return cs;
+}
+
+static void
+io_handler_source_finalized (gpointer data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ if (handler->watch)
+ dbus_watch_set_data (handler->watch, NULL, NULL);
+
+ g_free (handler);
+}
+
+static void
+io_handler_destroy_source (void *data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ if (handler->source)
+ {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+io_handler_watch_freed (void *data)
+{
+ IOHandler *handler;
+
+ handler = data;
+
+ handler->watch = NULL;
+
+ io_handler_destroy_source (handler);
+}
+
+static gboolean
+io_handler_dispatch (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ IOHandler *handler;
+ guint dbus_condition = 0;
+ DBusConnection *connection;
+
+ handler = data;
+
+ connection = handler->cs->connection;
+
+ if (connection)
+ dbus_connection_ref (connection);
+
+ if (condition & G_IO_IN)
+ dbus_condition |= DBUS_WATCH_READABLE;
+ if (condition & G_IO_OUT)
+ dbus_condition |= DBUS_WATCH_WRITABLE;
+ if (condition & G_IO_ERR)
+ dbus_condition |= DBUS_WATCH_ERROR;
+ if (condition & G_IO_HUP)
+ dbus_condition |= DBUS_WATCH_HANGUP;
+
+ /* Note that we don't touch the handler after this, because
+ * dbus may have disabled the watch and thus killed the
+ * handler.
+ */
+ dbus_watch_handle (handler->watch, dbus_condition);
+ handler = NULL;
+
+ if (connection)
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static void
+connection_setup_add_watch (ConnectionSetup *cs,
+ DBusWatch *watch)
+{
+ guint flags;
+ GIOCondition condition;
+ GIOChannel *channel;
+ IOHandler *handler;
+ int fd;
+
+ if (!dbus_watch_get_enabled (watch))
+ return;
+
+ g_assert (dbus_watch_get_data (watch) == NULL);
+
+ flags = dbus_watch_get_flags (watch);
+
+ condition = G_IO_ERR | G_IO_HUP;
+ if (flags & DBUS_WATCH_READABLE)
+ condition |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ condition |= G_IO_OUT;
+
+ handler = g_new0 (IOHandler, 1);
+ handler->cs = cs;
+ handler->watch = watch;
+
+#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
+ fd = dbus_watch_get_unix_fd (watch);
+#else
+ fd = dbus_watch_get_fd (watch);
+#endif
+ channel = g_io_channel_unix_new (fd);
+
+ handler->source = g_io_create_watch (channel, condition);
+ g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
+ io_handler_source_finalized);
+ g_source_attach (handler->source, cs->context);
+
+ cs->ios = g_slist_prepend (cs->ios, handler);
+
+ dbus_watch_set_data (watch, handler, io_handler_watch_freed);
+ g_io_channel_unref (channel);
+}
+
+static void
+connection_setup_remove_watch (ConnectionSetup *cs,
+ DBusWatch *watch)
+{
+ IOHandler *handler;
+
+ handler = dbus_watch_get_data (watch);
+
+ if (handler == NULL)
+ return;
+
+ io_handler_destroy_source (handler);
+}
+
+static void
+timeout_handler_source_finalized (gpointer data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ if (handler->timeout)
+ dbus_timeout_set_data (handler->timeout, NULL, NULL);
+
+ g_free (handler);
+}
+
+static void
+timeout_handler_destroy_source (void *data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ if (handler->source)
+ {
+ GSource *source = handler->source;
+ handler->source = NULL;
+ handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+static void
+timeout_handler_timeout_freed (void *data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ handler->timeout = NULL;
+
+ timeout_handler_destroy_source (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer data)
+{
+ TimeoutHandler *handler;
+
+ handler = data;
+
+ dbus_timeout_handle (handler->timeout);
+
+ return TRUE;
+}
+
+static void
+connection_setup_add_timeout (ConnectionSetup *cs,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return;
+
+ g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+ handler = g_new0 (TimeoutHandler, 1);
+ handler->cs = cs;
+ handler->timeout = timeout;
+
+ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+ g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
+ timeout_handler_source_finalized);
+ g_source_attach (handler->source, handler->cs->context);
+
+ cs->timeouts = g_slist_prepend (cs->timeouts, handler);
+
+ dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
+}
+
+static void
+connection_setup_remove_timeout (ConnectionSetup *cs,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ handler = dbus_timeout_get_data (timeout);
+
+ if (handler == NULL)
+ return;
+
+ timeout_handler_destroy_source (handler);
+}
+
+static void
+connection_setup_free (ConnectionSetup *cs)
+{
+ while (cs->ios)
+ io_handler_destroy_source (cs->ios->data);
+
+ while (cs->timeouts)
+ timeout_handler_destroy_source (cs->timeouts->data);
+
+ if (cs->message_queue_source)
+ {
+ GSource *source;
+
+ source = cs->message_queue_source;
+ cs->message_queue_source = NULL;
+
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+
+ g_main_context_unref (cs->context);
+ g_free (cs);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+ gpointer data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_add_watch (cs, watch);
+
+ return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+ gpointer data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_remove_watch (cs, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_watch_get_enabled (watch))
+ add_watch (watch, data);
+ else
+ remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return TRUE;
+
+ connection_setup_add_timeout (cs, timeout);
+
+ return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ ConnectionSetup *cs;
+
+ cs = data;
+
+ connection_setup_remove_timeout (cs, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_timeout_get_enabled (timeout))
+ add_timeout (timeout, data);
+ else
+ remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+ ConnectionSetup *cs = data;
+
+ g_main_context_wakeup (cs->context);
+}
+
+
+/* Move to a new context */
+static ConnectionSetup*
+connection_setup_new_from_old (GMainContext *context,
+ ConnectionSetup *old)
+{
+ GSList *tmp;
+ ConnectionSetup *cs;
+
+ g_assert (old->context != context);
+
+ cs = connection_setup_new (context, old->connection);
+
+ tmp = old->ios;
+ while (tmp != NULL)
+ {
+ IOHandler *handler = tmp->data;
+
+ connection_setup_add_watch (cs, handler->watch);
+
+ tmp = tmp->next;
+ }
+
+ tmp = old->timeouts;
+ while (tmp != NULL)
+ {
+ TimeoutHandler *handler = tmp->data;
+
+ connection_setup_add_timeout (cs, handler->timeout);
+
+ tmp = tmp->next;
+ }
+
+ return cs;
+}
+
+/** @} */ /* End of GLib bindings internals */
+
+/** @addtogroup DBusGLib
+ * @{
+ */
+
+/**
+ * Sets the watch and timeout functions of a #DBusConnection
+ * to integrate the connection with the GLib main loop.
+ * Pass in #NULL for the #GMainContext unless you're
+ * doing something specialized.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ *
+ * @param connection the connection
+ * @param context the #GMainContext or #NULL for default context
+ */
+void
+dbus_connection_setup_with_g_main (DBusConnection *connection,
+ GMainContext *context)
+{
+ ConnectionSetup *old_setup;
+ ConnectionSetup *cs;
+
+ /* FIXME we never free the slot, so its refcount just keeps growing,
+ * which is kind of broken.
+ */
+ dbus_connection_allocate_data_slot (&connection_slot);
+ if (connection_slot < 0)
+ goto nomem;
+
+ if (context == NULL)
+ context = g_main_context_default ();
+
+ cs = NULL;
+
+ old_setup = dbus_connection_get_data (connection, connection_slot);
+ if (old_setup != NULL)
+ {
+ if (old_setup->context == context)
+ return; /* nothing to do */
+
+ cs = connection_setup_new_from_old (context, old_setup);
+
+ /* Nuke the old setup */
+ dbus_connection_set_data (connection, connection_slot, NULL, NULL);
+ old_setup = NULL;
+ }
+
+ if (cs == NULL)
+ cs = connection_setup_new (context, connection);
+
+ if (!dbus_connection_set_data (connection, connection_slot, cs,
+ (DBusFreeFunction)connection_setup_free))
+ goto nomem;
+
+ if (!dbus_connection_set_watch_functions (connection,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ cs, NULL))
+ goto nomem;
+
+ if (!dbus_connection_set_timeout_functions (connection,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ cs, NULL))
+ goto nomem;
+
+ dbus_connection_set_wakeup_main_function (connection,
+ wakeup_main,
+ cs, NULL);
+
+ return;
+
+ nomem:
+ g_error ("Not enough memory to set up DBusConnection for use with GLib");
+}
+
+/**
+ * Sets the watch and timeout functions of a #DBusServer
+ * to integrate the server with the GLib main loop.
+ * In most cases the context argument should be #NULL.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ *
+ * @param server the server
+ * @param context the #GMainContext or #NULL for default
+ */
+void
+dbus_server_setup_with_g_main (DBusServer *server,
+ GMainContext *context)
+{
+ ConnectionSetup *old_setup;
+ ConnectionSetup *cs;
+
+ /* FIXME we never free the slot, so its refcount just keeps growing,
+ * which is kind of broken.
+ */
+ dbus_server_allocate_data_slot (&server_slot);
+ if (server_slot < 0)
+ goto nomem;
+
+ if (context == NULL)
+ context = g_main_context_default ();
+
+ cs = NULL;
+
+ old_setup = dbus_server_get_data (server, server_slot);
+ if (old_setup != NULL)
+ {
+ if (old_setup->context == context)
+ return; /* nothing to do */
+
+ cs = connection_setup_new_from_old (context, old_setup);
+
+ /* Nuke the old setup */
+ dbus_server_set_data (server, server_slot, NULL, NULL);
+ old_setup = NULL;
+ }
+
+ if (cs == NULL)
+ cs = connection_setup_new (context, NULL);
+
+ if (!dbus_server_set_data (server, server_slot, cs,
+ (DBusFreeFunction)connection_setup_free))
+ goto nomem;
+
+ if (!dbus_server_set_watch_functions (server,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ cs, NULL))
+ goto nomem;
+
+ if (!dbus_server_set_timeout_functions (server,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ cs, NULL))
+ goto nomem;
+
+ return;
+
+ nomem:
+ g_error ("Not enough memory to set up DBusServer for use with GLib");
+}
diff --git a/trunk/daemon/dbus-gmain.h b/trunk/daemon/dbus-gmain.h
new file mode 100644
index 00000000..8f0d0871
--- /dev/null
+++ b/trunk/daemon/dbus-gmain.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/* dbus-glib-lowlevel.h GLib integration details that require dbus/dbus.h
+ *
+ * Copyright (C) 2002, 2003 CodeFactory AB
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+#ifndef DBUS_GLIB_LOWLEVEL_H
+#define DBUS_GLIB_LOWLEVEL_H
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+void dbus_connection_setup_with_g_main (DBusConnection *connection,
+ GMainContext *context);
+void dbus_server_setup_with_g_main (DBusServer *server,
+ GMainContext *context);
+
+G_END_DECLS
+
+#endif /* DBUS_GLIB_LOWLEVEL_H */
+
+
+
diff --git a/trunk/daemon/dns-sd.mount.in b/trunk/daemon/dns-sd.mount.in
new file mode 100644
index 00000000..1224ae69
--- /dev/null
+++ b/trunk/daemon/dns-sd.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=dns-sd
+Exec=@libexecdir@/gvfsd-dnssd
+AutoMount=true
diff --git a/trunk/daemon/ftp.mount.in b/trunk/daemon/ftp.mount.in
new file mode 100644
index 00000000..e1133392
--- /dev/null
+++ b/trunk/daemon/ftp.mount.in
@@ -0,0 +1,7 @@
+[Mount]
+Type=ftp
+Exec=@libexecdir@/gvfsd-ftp
+AutoMount=false
+Scheme=ftp
+DefaultPort=21
+HostnameIsInetAddress=true
diff --git a/trunk/daemon/gphoto2.mount.in b/trunk/daemon/gphoto2.mount.in
new file mode 100644
index 00000000..2602afa3
--- /dev/null
+++ b/trunk/daemon/gphoto2.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=gphoto2
+Exec=@libexecdir@/gvfsd-gphoto2
+AutoMount=false
diff --git a/trunk/daemon/gvfs-daemon.service.in b/trunk/daemon/gvfs-daemon.service.in
new file mode 100644
index 00000000..00fe5315
--- /dev/null
+++ b/trunk/daemon/gvfs-daemon.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.vfs.Daemon
+Exec=@libexecdir@/gvfsd
diff --git a/trunk/daemon/gvfsbackend.c b/trunk/daemon/gvfsbackend.c
new file mode 100644
index 00000000..0eb36048
--- /dev/null
+++ b/trunk/daemon/gvfsbackend.c
@@ -0,0 +1,677 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsbackend.h"
+#include "gvfsjobsource.h"
+#include "gvfsdaemonprotocol.h"
+#include <gvfsjobopenforread.h>
+#include <gvfsjobopeniconforread.h>
+#include <gvfsjobopenforwrite.h>
+#include <gvfsjobqueryinfo.h>
+#include <gvfsjobqueryfsinfo.h>
+#include <gvfsjobsetdisplayname.h>
+#include <gvfsjobenumerate.h>
+#include <gvfsjobdelete.h>
+#include <gvfsjobtrash.h>
+#include <gvfsjobunmount.h>
+#include <gvfsjobmountmountable.h>
+#include <gvfsjobunmountmountable.h>
+#include <gvfsjobmakedirectory.h>
+#include <gvfsjobmakesymlink.h>
+#include <gvfsjobcreatemonitor.h>
+#include <gvfsjobcopy.h>
+#include <gvfsjobmove.h>
+#include <gvfsjobpush.h>
+#include <gvfsjobpull.h>
+#include <gvfsjobsetattribute.h>
+#include <gvfsjobqueryattributes.h>
+#include <gdbusutils.h>
+
+enum {
+ PROP_0,
+ PROP_OBJECT_PATH,
+ PROP_DAEMON
+};
+
+struct _GVfsBackendPrivate
+{
+ GVfsDaemon *daemon;
+ char *object_path;
+
+ char *display_name;
+ char *stable_name;
+ char **x_content_types;
+ GIcon *icon;
+ char *prefered_filename_encoding;
+ gboolean user_visible;
+ GMountSpec *mount_spec;
+};
+
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+
+static void g_vfs_backend_job_source_iface_init (GVfsJobSourceIface *iface);
+static void g_vfs_backend_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void g_vfs_backend_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static GObject* g_vfs_backend_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+static DBusHandlerResult backend_dbus_handler (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+
+G_DEFINE_TYPE_WITH_CODE (GVfsBackend, g_vfs_backend, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_VFS_TYPE_JOB_SOURCE,
+ g_vfs_backend_job_source_iface_init))
+
+
+static GHashTable *registered_backends = NULL;
+
+void
+g_vfs_register_backend (GType backend_type,
+ const char *type)
+{
+ if (registered_backends == NULL)
+ registered_backends = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ g_hash_table_insert (registered_backends,
+ g_strdup (type), (void *)backend_type);
+}
+
+GType
+g_vfs_lookup_backend (const char *type)
+{
+ gpointer res;
+
+ if (registered_backends != NULL)
+ {
+ res = g_hash_table_lookup (registered_backends, type);
+ if (res != NULL)
+ return (GType)res;
+ }
+
+ return G_TYPE_INVALID;
+}
+
+static void
+g_vfs_backend_finalize (GObject *object)
+{
+ GVfsBackend *backend;
+
+ backend = G_VFS_BACKEND (object);
+
+ g_vfs_daemon_unregister_path (backend->priv->daemon, backend->priv->object_path);
+ g_object_unref (backend->priv->daemon);
+ g_free (backend->priv->object_path);
+
+ g_free (backend->priv->display_name);
+ g_free (backend->priv->stable_name);
+ g_strfreev (backend->priv->x_content_types);
+ if (backend->priv->icon != NULL)
+ g_object_unref (backend->priv->icon);
+ g_free (backend->priv->prefered_filename_encoding);
+ if (backend->priv->mount_spec)
+ g_mount_spec_unref (backend->priv->mount_spec);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_job_source_iface_init (GVfsJobSourceIface *iface)
+{
+}
+
+static void
+g_vfs_backend_class_init (GVfsBackendClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GVfsBackendPrivate));
+
+ gobject_class->constructor = g_vfs_backend_constructor;
+ gobject_class->finalize = g_vfs_backend_finalize;
+ gobject_class->set_property = g_vfs_backend_set_property;
+ gobject_class->get_property = g_vfs_backend_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_OBJECT_PATH,
+ g_param_spec_string ("object-path",
+ P_("Backend object path"),
+ P_("The dbus object path for the backend object."),
+ "",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (gobject_class,
+ PROP_DAEMON,
+ g_param_spec_object ("daemon",
+ P_("Daemon"),
+ P_("The daemon this backend is handled by."),
+ G_VFS_TYPE_DAEMON,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_vfs_backend_init (GVfsBackend *backend)
+{
+ backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, G_VFS_TYPE_BACKEND, GVfsBackendPrivate);
+ backend->priv->icon = NULL;
+ backend->priv->prefered_filename_encoding = g_strdup ("");
+ backend->priv->display_name = g_strdup ("");
+ backend->priv->stable_name = g_strdup ("");
+ backend->priv->user_visible = TRUE;
+}
+
+static void
+g_vfs_backend_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (object);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT_PATH:
+ backend->priv->object_path = g_value_dup_string (value);
+ break;
+ case PROP_DAEMON:
+ backend->priv->daemon = G_VFS_DAEMON (g_value_dup_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_backend_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (object);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT_PATH:
+ g_value_set_string (value, backend->priv->object_path);
+ break;
+ case PROP_DAEMON:
+ g_value_set_object (value, backend->priv->daemon);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject*
+g_vfs_backend_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GVfsBackend *backend;
+
+ object = (* G_OBJECT_CLASS (g_vfs_backend_parent_class)->constructor) (type,
+ n_construct_properties,
+ construct_params);
+ backend = G_VFS_BACKEND (object);
+
+ g_vfs_daemon_register_path (backend->priv->daemon,
+ backend->priv->object_path,
+ backend_dbus_handler,
+ backend);
+
+ return object;
+}
+
+GVfsDaemon *
+g_vfs_backend_get_daemon (GVfsBackend *backend)
+{
+ return backend->priv->daemon;
+}
+
+
+void
+g_vfs_backend_set_display_name (GVfsBackend *backend,
+ const char *display_name)
+{
+ g_free (backend->priv->display_name);
+ backend->priv->display_name = g_strdup (display_name);
+}
+
+/**
+ * g_vfs_backend_set_stable_name:
+ * @backend: backend
+ * @stable_name: the stable name
+ *
+ * For filesystems that can change the name during the lifetime
+ * of the filesystem this can be uses to set a separate stable
+ * name. This is used for instance as the directory representing
+ * the mounted file system in the standard UNIX file system
+ * namespace.
+ *
+ * If this function isn't called, the value passed to
+ * g_vfs_backend_set_display_name() will be used instead.
+ **/
+void
+g_vfs_backend_set_stable_name (GVfsBackend *backend,
+ const char *stable_name)
+{
+ g_free (backend->priv->stable_name);
+ backend->priv->stable_name = g_strdup (stable_name);
+}
+
+/**
+ * g_vfs_backend_set_x_content_types:
+ * @backend: backend
+ * @x_content_types: the x-content types
+ *
+ * For backends where the x-content type is known ahead of time and
+ * won't change (such as a CDDA audio disc backend), this function
+ * should be called when the backend is constructed with the given
+ * types.
+ *
+ * See the <ulink url="http://www.freedesktop.org/wiki/Specifications/shared-mime-info-spec">shared-mime-info</ulink>
+ * specification for more on x-content types.
+ **/
+void
+g_vfs_backend_set_x_content_types (GVfsBackend *backend,
+ char **x_content_types)
+{
+ g_strfreev (backend->priv->x_content_types);
+ backend->priv->x_content_types = g_strdupv (x_content_types);
+}
+
+void
+g_vfs_backend_set_icon_name (GVfsBackend *backend,
+ const char *icon_name)
+{
+ if (backend->priv->icon != NULL)
+ g_object_unref (backend->priv->icon);
+ backend->priv->icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+}
+
+void
+g_vfs_backend_set_icon (GVfsBackend *backend,
+ GIcon *icon)
+{
+ if (backend->priv->icon != NULL)
+ g_object_unref (backend->priv->icon);
+ backend->priv->icon = g_object_ref (icon);
+}
+
+void
+g_vfs_backend_set_prefered_filename_encoding (GVfsBackend *backend,
+ const char *prefered_filename_encoding)
+{
+ g_free (backend->priv->prefered_filename_encoding);
+ backend->priv->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
+}
+
+void
+g_vfs_backend_set_user_visible (GVfsBackend *backend,
+ gboolean user_visible)
+{
+ backend->priv->user_visible = user_visible;
+}
+
+void
+g_vfs_backend_set_mount_spec (GVfsBackend *backend,
+ GMountSpec *mount_spec)
+{
+ if (backend->priv->mount_spec)
+ g_mount_spec_unref (backend->priv->mount_spec);
+ backend->priv->mount_spec = g_mount_spec_ref (mount_spec);
+}
+
+const char *
+g_vfs_backend_get_backend_type (GVfsBackend *backend)
+{
+ if (backend->priv->mount_spec)
+ return g_mount_spec_get_type (backend->priv->mount_spec);
+ return NULL;
+}
+
+const char *
+g_vfs_backend_get_display_name (GVfsBackend *backend)
+{
+ return backend->priv->display_name;
+}
+
+const char *
+g_vfs_backend_get_stable_name (GVfsBackend *backend)
+{
+ return backend->priv->stable_name;
+}
+
+char **
+g_vfs_backend_get_x_content_types (GVfsBackend *backend)
+{
+ return backend->priv->x_content_types;
+}
+
+GIcon *
+g_vfs_backend_get_icon (GVfsBackend *backend)
+{
+ return backend->priv->icon;
+}
+
+GMountSpec *
+g_vfs_backend_get_mount_spec (GVfsBackend *backend)
+{
+ return backend->priv->mount_spec;
+}
+
+static void
+get_thumbnail_attributes (const char *uri,
+ GFileInfo *info)
+{
+ GChecksum *checksum;
+ char *filename;
+ char *basename;
+
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
+
+ basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
+ g_checksum_free (checksum);
+
+ filename = g_build_filename (g_get_home_dir (),
+ ".thumbnails", "normal", basename,
+ NULL);
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH, filename);
+ else
+ {
+ g_free (filename);
+ filename = g_build_filename (g_get_home_dir (),
+ ".thumbnails", "fail",
+ "gnome-thumbnail-factory",
+ basename,
+ NULL);
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED, TRUE);
+ }
+ g_free (basename);
+ g_free (filename);
+}
+
+void
+g_vfs_backend_add_auto_info (GVfsBackend *backend,
+ GFileAttributeMatcher *matcher,
+ GFileInfo *info,
+ const char *uri)
+{
+ GMountSpec *spec;
+ char *id;
+
+ if (g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_ID_FILESYSTEM))
+ {
+ spec = g_vfs_backend_get_mount_spec (backend);
+ if (spec)
+ {
+ id = g_mount_spec_to_string (spec);
+ g_file_info_set_attribute_string (info,
+ G_FILE_ATTRIBUTE_ID_FILESYSTEM,
+ id);
+ g_free (id);
+ }
+ }
+
+ if (uri != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH))
+ get_thumbnail_attributes (uri, info);
+
+}
+
+static DBusHandlerResult
+backend_dbus_handler (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GVfsBackend *backend = user_data;
+ GVfsJob *job;
+
+ job = NULL;
+
+ g_debug ("backend_dbus_handler %s:%s\n",
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message));
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_UNMOUNT))
+ job = g_vfs_job_unmount_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ))
+ job = g_vfs_job_open_for_read_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ))
+ job = g_vfs_job_open_icon_for_read_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_QUERY_INFO))
+ job = g_vfs_job_query_info_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO))
+ job = g_vfs_job_query_fs_info_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_ENUMERATE))
+ job = g_vfs_job_enumerate_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE))
+ job = g_vfs_job_open_for_write_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE))
+ job = g_vfs_job_mount_mountable_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE))
+ job = g_vfs_job_unmount_mountable_new (connection, message, backend, FALSE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE))
+ job = g_vfs_job_unmount_mountable_new (connection, message, backend, TRUE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME))
+ job = g_vfs_job_set_display_name_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_DELETE))
+ job = g_vfs_job_delete_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_TRASH))
+ job = g_vfs_job_trash_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY))
+ job = g_vfs_job_make_directory_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK))
+ job = g_vfs_job_make_symlink_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_COPY))
+ job = g_vfs_job_copy_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_PUSH))
+ job = g_vfs_job_push_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_PULL))
+ job = g_vfs_job_pull_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_MOVE))
+ job = g_vfs_job_move_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE))
+ job = g_vfs_job_set_attribute_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES))
+ job = g_vfs_job_query_attributes_new (connection, message, backend, FALSE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES))
+ job = g_vfs_job_query_attributes_new (connection, message, backend, TRUE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR))
+ job = g_vfs_job_create_monitor_new (connection, message, backend, TRUE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR))
+ job = g_vfs_job_create_monitor_new (connection, message, backend, FALSE);
+
+ if (job)
+ {
+ g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), job);
+ g_object_unref (job);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+void
+g_vfs_backend_register_mount (GVfsBackend *backend,
+ GAsyncDBusCallback callback,
+ gpointer user_data)
+{
+ const char *stable_name;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ dbus_bool_t user_visible;
+ char *x_content_types_string;
+ char *icon_str;
+
+ if (backend->priv->x_content_types != NULL && g_strv_length (backend->priv->x_content_types) > 0)
+ x_content_types_string = g_strjoinv (" ", backend->priv->x_content_types);
+ else
+ x_content_types_string = g_strdup ("");
+
+ if (backend->priv->icon != NULL)
+ icon_str = g_icon_to_string (backend->priv->icon);
+ else
+ icon_str = g_strdup ("");
+
+ message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT);
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ if (backend->priv->stable_name != NULL &&
+ *backend->priv->stable_name != 0)
+ stable_name = backend->priv->stable_name;
+ else
+ stable_name = backend->priv->display_name;
+
+ user_visible = backend->priv->user_visible;
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path,
+ DBUS_TYPE_STRING, &backend->priv->display_name,
+ DBUS_TYPE_STRING, &stable_name,
+ DBUS_TYPE_STRING, &x_content_types_string,
+ DBUS_TYPE_STRING, &icon_str,
+ DBUS_TYPE_STRING, &backend->priv->prefered_filename_encoding,
+ DBUS_TYPE_BOOLEAN, &user_visible,
+ 0))
+ _g_dbus_oom ();
+
+ dbus_message_iter_init_append (message, &iter);
+ g_mount_spec_to_dbus (&iter, backend->priv->mount_spec);
+
+ dbus_message_set_auto_start (message, TRUE);
+
+ _g_dbus_connection_call_async (NULL, message, -1,
+ callback, user_data);
+ dbus_message_unref (message);
+
+ g_free (x_content_types_string);
+ g_free (icon_str);
+}
+
+void
+g_vfs_backend_unregister_mount (GVfsBackend *backend,
+ GAsyncDBusCallback callback,
+ gpointer user_data)
+{
+ DBusMessage *message;
+
+ message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_UNREGISTER_MOUNT);
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path,
+ 0))
+ _g_dbus_oom ();
+
+ _g_dbus_connection_call_async (NULL, message, -1,
+ callback, user_data);
+ dbus_message_unref (message);
+}
diff --git a/trunk/daemon/gvfsbackend.h b/trunk/daemon/gvfsbackend.h
new file mode 100644
index 00000000..243d978c
--- /dev/null
+++ b/trunk/daemon/gvfsbackend.h
@@ -0,0 +1,463 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_H__
+#define __G_VFS_BACKEND_H__
+
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+#include <gvfsdaemon.h>
+#include <gvfsjob.h>
+#include <gmountspec.h>
+#include <gdbusutils.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND (g_vfs_backend_get_type ())
+#define G_VFS_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND, GVfsBackend))
+#define G_VFS_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND, GVfsBackendClass))
+#define G_VFS_IS_BACKEND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND))
+#define G_VFS_IS_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND))
+#define G_VFS_BACKEND_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND, GVfsBackendClass))
+
+typedef struct _GVfsBackend GVfsBackend;
+typedef struct _GVfsBackendPrivate GVfsBackendPrivate;
+typedef struct _GVfsBackendClass GVfsBackendClass;
+
+typedef struct _GVfsJobMount GVfsJobMount;
+typedef struct _GVfsJobUnmount GVfsJobUnmount;
+typedef struct _GVfsJobMountMountable GVfsJobMountMountable;
+typedef struct _GVfsJobUnmountMountable GVfsJobUnmountMountable;
+typedef struct _GVfsJobOpenForRead GVfsJobOpenForRead;
+typedef struct _GVfsJobOpenIconForRead GVfsJobOpenIconForRead;
+typedef struct _GVfsJobSeekRead GVfsJobSeekRead;
+typedef struct _GVfsJobCloseRead GVfsJobCloseRead;
+typedef struct _GVfsJobRead GVfsJobRead;
+typedef struct _GVfsJobOpenForWrite GVfsJobOpenForWrite;
+typedef struct _GVfsJobWrite GVfsJobWrite;
+typedef struct _GVfsJobSeekWrite GVfsJobSeekWrite;
+typedef struct _GVfsJobCloseWrite GVfsJobCloseWrite;
+typedef struct _GVfsJobQueryInfo GVfsJobQueryInfo;
+typedef struct _GVfsJobQueryInfoRead GVfsJobQueryInfoRead;
+typedef struct _GVfsJobQueryInfoWrite GVfsJobQueryInfoWrite;
+typedef struct _GVfsJobQueryFsInfo GVfsJobQueryFsInfo;
+typedef struct _GVfsJobEnumerate GVfsJobEnumerate;
+typedef struct _GVfsJobSetDisplayName GVfsJobSetDisplayName;
+typedef struct _GVfsJobTrash GVfsJobTrash;
+typedef struct _GVfsJobDelete GVfsJobDelete;
+typedef struct _GVfsJobMakeDirectory GVfsJobMakeDirectory;
+typedef struct _GVfsJobMakeSymlink GVfsJobMakeSymlink;
+typedef struct _GVfsJobCopy GVfsJobCopy;
+typedef struct _GVfsJobMove GVfsJobMove;
+typedef struct _GVfsJobPush GVfsJobPush;
+typedef struct _GVfsJobPull GVfsJobPull;
+typedef struct _GVfsJobSetAttribute GVfsJobSetAttribute;
+typedef struct _GVfsJobQueryAttributes GVfsJobQueryAttributes;
+typedef struct _GVfsJobCreateMonitor GVfsJobCreateMonitor;
+
+typedef gpointer GVfsBackendHandle;
+
+struct _GVfsBackend
+{
+ GObject parent_instance;
+
+ GVfsBackendPrivate *priv;
+};
+
+struct _GVfsBackendClass
+{
+ GObjectClass parent_class;
+
+ /* vtable */
+
+ /* These try_ calls should be fast and non-blocking, scheduling the i/o
+ * operations async (or on a thread) or reading from cache.
+ * Returning FALSE means "Can't do this now or async", which
+ * means the non-try_ version will be scheduled in a worker
+ * thread.
+ * A NULL here means operation not supported
+ */
+
+ void (*unmount) (GVfsBackend *backend,
+ GVfsJobUnmount *job);
+ gboolean (*try_unmount) (GVfsBackend *backend,
+ GVfsJobUnmount *job);
+ void (*mount) (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount);
+ gboolean (*try_mount) (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount);
+ void (*mount_mountable) (GVfsBackend *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source);
+ gboolean (*try_mount_mountable)(GVfsBackend *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source);
+ void (*unmount_mountable) (GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags);
+ gboolean (*try_unmount_mountable)(GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags);
+ void (*eject_mountable) (GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags);
+ gboolean (*try_eject_mountable)(GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags);
+ void (*open_for_read) (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename);
+ gboolean (*try_open_for_read) (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename);
+ void (*open_icon_for_read) (GVfsBackend *backend,
+ GVfsJobOpenIconForRead *job,
+ const char *icon_id);
+ gboolean (*try_open_icon_for_read) (GVfsBackend *backend,
+ GVfsJobOpenIconForRead *job,
+ const char *icon_id);
+ void (*close_read) (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle);
+ gboolean (*try_close_read) (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle);
+ void (*read) (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested);
+ gboolean (*try_read) (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested);
+ void (*seek_on_read) (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type);
+ gboolean (*try_seek_on_read) (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type);
+ gboolean (*try_create) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags);
+ void (*create) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags);
+ gboolean (*try_append_to) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags);
+ void (*append_to) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags);
+ gboolean (*try_replace) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags);
+ void (*replace) (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags);
+ void (*close_write) (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle);
+ gboolean (*try_close_write) (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle);
+ void (*write) (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize buffer_size);
+ gboolean (*try_write) (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize buffer_size);
+ void (*seek_on_write) (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type);
+ gboolean (*try_seek_on_write) (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type);
+ void (*query_info) (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ gboolean (*try_query_info) (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ void (*query_info_on_read)(GVfsBackend *backend,
+ GVfsJobQueryInfoRead *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ gboolean (*try_query_info_on_read)(GVfsBackend *backend,
+ GVfsJobQueryInfoRead *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ void (*query_info_on_write)(GVfsBackend *backend,
+ GVfsJobQueryInfoWrite *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ gboolean (*try_query_info_on_write)(GVfsBackend *backend,
+ GVfsJobQueryInfoWrite *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ void (*query_fs_info) (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ gboolean (*try_query_fs_info) (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher);
+ void (*enumerate) (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags);
+ gboolean (*try_enumerate) (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags);
+ void (*set_display_name) (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name);
+ gboolean (*try_set_display_name) (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name);
+ void (*delete) (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename);
+ gboolean (*try_delete) (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename);
+ void (*trash) (GVfsBackend *backend,
+ GVfsJobTrash *job,
+ const char *filename);
+ gboolean (*try_trash) (GVfsBackend *backend,
+ GVfsJobTrash *job,
+ const char *filename);
+ void (*make_directory) (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename);
+ gboolean (*try_make_directory)(GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename);
+ void (*make_symlink) (GVfsBackend *backend,
+ GVfsJobMakeSymlink *make_symlink,
+ const char *filename,
+ const char *symlink_value);
+ gboolean (*try_make_symlink) (GVfsBackend *backend,
+ GVfsJobMakeSymlink *make_symlink,
+ const char *filename,
+ const char *symlink_value);
+ void (*copy) (GVfsBackend *backend,
+ GVfsJobCopy *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ gboolean (*try_copy) (GVfsBackend *backend,
+ GVfsJobCopy *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ void (*move) (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ gboolean (*try_move) (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ void (*push) (GVfsBackend *backend,
+ GVfsJobPush *job,
+ const char *destination,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ gboolean (*try_push) (GVfsBackend *backend,
+ GVfsJobPush *job,
+ const char *destination,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ void (*pull) (GVfsBackend *backend,
+ GVfsJobPull *job,
+ const char *source,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ gboolean (*try_pull) (GVfsBackend *backend,
+ GVfsJobPull *job,
+ const char *source,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data);
+ void (*set_attribute) (GVfsBackend *backend,
+ GVfsJobSetAttribute *set_attribute,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags);
+ gboolean (*try_set_attribute) (GVfsBackend *backend,
+ GVfsJobSetAttribute *set_attribute,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags);
+ void (*create_dir_monitor)(GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags);
+ gboolean (*try_create_dir_monitor) (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags);
+ void (*create_file_monitor)(GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags);
+ gboolean (*try_create_file_monitor) (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags);
+ void (*query_settable_attributes) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+ gboolean (*try_query_settable_attributes) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+ void (*query_writable_namespaces) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+ gboolean (*try_query_writable_namespaces) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+};
+
+GType g_vfs_backend_get_type (void) G_GNUC_CONST;
+
+void g_vfs_register_backend (GType backend_type,
+ const char *type);
+GType g_vfs_lookup_backend (const char *type);
+
+void g_vfs_backend_set_display_name (GVfsBackend *backend,
+ const char *display_name);
+void g_vfs_backend_set_stable_name (GVfsBackend *backend,
+ const char *stable_name);
+void g_vfs_backend_set_x_content_types (GVfsBackend *backend,
+ char **x_content_types);
+void g_vfs_backend_set_icon_name (GVfsBackend *backend,
+ const char *icon_name);
+void g_vfs_backend_set_icon (GVfsBackend *backend,
+ GIcon *icon);
+void g_vfs_backend_set_prefered_filename_encoding (GVfsBackend *backend,
+ const char *prefered_filename_encoding);
+void g_vfs_backend_set_user_visible (GVfsBackend *backend,
+ gboolean user_visible);
+void g_vfs_backend_set_mount_spec (GVfsBackend *backend,
+ GMountSpec *mount_spec);
+void g_vfs_backend_register_mount (GVfsBackend *backend,
+ GAsyncDBusCallback callback,
+ gpointer user_data);
+void g_vfs_backend_unregister_mount (GVfsBackend *backend,
+ GAsyncDBusCallback callback,
+ gpointer user_data);
+const char *g_vfs_backend_get_backend_type (GVfsBackend *backend);
+const char *g_vfs_backend_get_display_name (GVfsBackend *backend);
+const char *g_vfs_backend_get_stable_name (GVfsBackend *backend);
+char **g_vfs_backend_get_x_content_types (GVfsBackend *backend);
+GIcon *g_vfs_backend_get_icon (GVfsBackend *backend);
+GMountSpec *g_vfs_backend_get_mount_spec (GVfsBackend *backend);
+GVfsDaemon *g_vfs_backend_get_daemon (GVfsBackend *backend);
+
+void g_vfs_backend_add_auto_info (GVfsBackend *backend,
+ GFileAttributeMatcher *matcher,
+ GFileInfo *info,
+ const char *uri);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_H__ */
diff --git a/trunk/daemon/gvfsbackendarchive.c b/trunk/daemon/gvfsbackendarchive.c
new file mode 100644
index 00000000..bbca3cad
--- /dev/null
+++ b/trunk/daemon/gvfsbackendarchive.c
@@ -0,0 +1,793 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Benjmain Otte <otte@gnome.org>
+ */
+
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <string.h>
+#include <archive.h>
+#include <archive_entry.h>
+
+#include "gvfsbackendarchive.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsdaemonutils.h"
+#include "gvfskeyring.h"
+
+#define MOUNT_ICON_NAME "drive-removable-media"
+
+/* #define PRINT_DEBUG */
+
+#ifdef PRINT_DEBUG
+#define DEBUG g_print
+#else
+#define DEBUG(...)
+#endif
+
+/*** TYPE DEFINITIONS ***/
+
+typedef struct _ArchiveFile ArchiveFile;
+struct _ArchiveFile {
+ char * name; /* name of the file inside the archive */
+ GFileInfo * info; /* file info created from archive_entry */
+ GSList * children; /* (unordered) list of child files */
+};
+
+struct _GVfsBackendArchive
+{
+ GVfsBackend backend;
+
+ GFile * file;
+ ArchiveFile * files; /* the tree of files */
+};
+
+G_DEFINE_TYPE (GVfsBackendArchive, g_vfs_backend_archive, G_VFS_TYPE_BACKEND)
+
+/*** AN ARCHIVE WE CAN OPERATE ON ***/
+
+typedef struct {
+ struct archive * archive;
+ GFile * file;
+ GFileInputStream *stream;
+ GVfsJob * job;
+ GError * error;
+ guchar data[4096];
+} GVfsArchive;
+
+#define gvfs_archive_return(d) ((d)->error ? ARCHIVE_FATAL : ARCHIVE_OK)
+
+static int
+gvfs_archive_open (struct archive *archive,
+ void *data)
+{
+ GVfsArchive *d = data;
+
+ DEBUG ("OPEN\n");
+ g_assert (d->stream == NULL);
+ d->stream = g_file_read (d->file,
+ d->job->cancellable,
+ &d->error);
+ return gvfs_archive_return (d);
+}
+
+static ssize_t
+gvfs_archive_read (struct archive *archive,
+ void *data,
+ const void **buffer)
+{
+ GVfsArchive *d = data;
+ gssize read_bytes;
+
+ *buffer = d->data;
+ read_bytes = g_input_stream_read (G_INPUT_STREAM (d->stream),
+ d->data,
+ sizeof (d->data),
+ d->job->cancellable,
+ &d->error);
+
+ DEBUG ("READ %d\n", (int) read_bytes);
+ return read_bytes;
+}
+
+static off_t
+gvfs_archive_skip (struct archive *archive,
+ void *data,
+ off_t request)
+{
+ GVfsArchive *d = data;
+
+ if (g_seekable_can_seek (G_SEEKABLE (d->stream)))
+ g_seekable_seek (G_SEEKABLE (d->stream),
+ request,
+ G_SEEK_CUR,
+ d->job->cancellable,
+ &d->error);
+ else
+ return 0;
+
+ if (d->error)
+ {
+ g_clear_error (&d->error);
+ request = 0;
+ }
+ DEBUG ("SEEK %d (%d)\n", (int) request,
+ (int) g_seekable_tell (G_SEEKABLE (d->stream)));
+
+ return request;
+}
+
+static int
+gvfs_archive_close (struct archive *archive,
+ void *data)
+{
+ GVfsArchive *d = data;
+
+ DEBUG ("CLOSE\n");
+ g_object_unref (d->stream);
+ d->stream = NULL;
+ return ARCHIVE_OK;
+}
+
+#define gvfs_archive_in_error(archive) ((archive)->error != NULL)
+
+static void
+gvfs_archive_push_job (GVfsArchive *archive, GVfsJob *job)
+{
+ archive->job = job;
+}
+
+static void
+gvfs_archive_pop_job (GVfsArchive *archive)
+{
+ if (archive->job == NULL)
+ return;
+
+ DEBUG ("popping job %s\n", G_OBJECT_TYPE_NAME (archive->job));
+ if (archive->error)
+ {
+ g_vfs_job_failed_from_error (archive->job, archive->error);
+ g_clear_error (&archive->error);
+ }
+ else if (archive_errno (archive->archive))
+ {
+ g_vfs_job_failed_literal (archive->job,
+ G_IO_ERROR,
+ archive_errno (archive->archive),
+ archive_error_string (archive->archive));
+ }
+ else
+ g_vfs_job_succeeded (archive->job);
+
+
+ archive->job = NULL;
+}
+
+static void
+gvfs_archive_finish (GVfsArchive *archive)
+{
+ gvfs_archive_pop_job (archive);
+
+ archive_read_finish (archive->archive);
+ g_slice_free (GVfsArchive, archive);
+}
+
+/* NB: assumes an GVfsArchive initialized with ARCHIVE_DATA_INIT */
+static GVfsArchive *
+gvfs_archive_new (GVfsBackendArchive *ba, GVfsJob *job)
+{
+ GVfsArchive *d;
+
+ d = g_slice_new0 (GVfsArchive);
+
+ d->file = ba->file;
+ gvfs_archive_push_job (d, job);
+
+ d->archive = archive_read_new ();
+ archive_read_support_compression_all (d->archive);
+ archive_read_support_format_all (d->archive);
+ archive_read_open2 (d->archive,
+ d,
+ gvfs_archive_open,
+ gvfs_archive_read,
+ gvfs_archive_skip,
+ gvfs_archive_close);
+
+ return d;
+}
+
+/*** BACKEND ***/
+
+static void
+g_vfs_backend_archive_finalize (GObject *object)
+{
+ GVfsBackendArchive *archive = G_VFS_BACKEND_ARCHIVE (object);
+
+ g_assert (archive->file == NULL);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_archive_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_archive_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_archive_init (GVfsBackendArchive *archive)
+{
+}
+
+/*** FILE TREE HANDLING ***/
+
+/* NB: filename must NOT start with a slash */
+static ArchiveFile *
+archive_file_get_from_path (ArchiveFile *file, const char *filename, gboolean add)
+{
+ char **names = g_strsplit (filename, "/", -1);
+ ArchiveFile *cur;
+ GSList *walk;
+ guint i;
+
+ DEBUG ("%s %s\n", add ? "add" : "find", filename);
+ for (i = 0; file && names[i] != NULL; i++)
+ {
+ cur = NULL;
+ for (walk = file->children; walk; walk = walk->next)
+ {
+ cur = walk->data;
+ if (g_str_equal (cur->name, names[i]))
+ break;
+ cur = NULL;
+ }
+ if (cur == NULL && add != FALSE)
+ {
+ DEBUG ("adding node %s to %s\n", names[i], file->name);
+ /* (hopefully) clever trick to avoid string copy */
+ if (names[i][0] != 0 &&
+ strcmp (names[i], ".") != 0)
+ {
+ cur = g_slice_new0 (ArchiveFile);
+ cur->name = names[i];
+ names[i] = NULL;
+ file->children = g_slist_prepend (file->children, cur);
+ }
+ else
+ {
+ /* happens when adding directories, their path ends with a / */
+ /* Can also happen with "." in e.g. iso files */
+ g_assert (names[i + 1] == NULL);
+ g_free (names[i]);
+ names[i] = NULL;
+ cur = file;
+ }
+ }
+ file = cur;
+ }
+ g_strfreev (names);
+ return file;
+}
+#define archive_file_find(ba, filename) archive_file_get_from_path((ba)->files, (filename) + 1, FALSE)
+
+static void
+create_root_file (GVfsBackendArchive *ba)
+{
+ ArchiveFile *root = g_slice_new0 (ArchiveFile);
+ GFileInfo *info;
+ char *s, *display_name;
+ GIcon *icon;
+
+ root = g_slice_new0 (ArchiveFile);
+ root->name = g_strdup ("/");
+ ba->files = root;
+
+ info = g_file_info_new ();
+ root->info = info;
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+
+ g_file_info_set_name (info, "/");
+ s = g_file_get_basename (ba->file);
+ /* FIXME: this should really be "/ in %s", but can't change
+ due to string freeze. */
+ display_name = g_strdup_printf (_("/ on %s"), s);
+ g_free (s);
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ g_file_info_set_edit_name (info, "/");
+
+ g_file_info_set_content_type (info, "inode/directory");
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, "inode/directory");
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+}
+
+static void
+archive_file_set_info_from_entry (ArchiveFile * file,
+ struct archive_entry *entry)
+{
+ GFileInfo *info = g_file_info_new ();
+ GFileType type;
+ file->info = info;
+
+ DEBUG ("setting up %s (%s)\n", archive_entry_pathname (entry), file->name);
+
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_ACCESS,
+ archive_entry_atime (entry));
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
+ archive_entry_atime_nsec (entry) / 1000);
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_CHANGED,
+ archive_entry_ctime (entry));
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_TIME_CHANGED_USEC,
+ archive_entry_ctime_nsec (entry) / 1000);
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ archive_entry_mtime (entry));
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
+ archive_entry_mtime_nsec (entry) / 1000);
+
+ switch (archive_entry_filetype (entry))
+ {
+ case AE_IFREG:
+ type = G_FILE_TYPE_REGULAR;
+ break;
+ case AE_IFLNK:
+ g_file_info_set_symlink_target (info,
+ archive_entry_symlink (entry));
+ type = G_FILE_TYPE_SYMBOLIC_LINK;
+ break;
+ case AE_IFDIR:
+ type = G_FILE_TYPE_DIRECTORY;
+ break;
+ case AE_IFCHR:
+ case AE_IFBLK:
+ case AE_IFIFO:
+ type = G_FILE_TYPE_SPECIAL;
+ break;
+ default:
+ g_warning ("unknown file type %u", archive_entry_filetype (entry));
+ type = G_FILE_TYPE_SPECIAL;
+ break;
+ }
+ g_file_info_set_name (info, file->name);
+ gvfs_file_info_populate_default (info,
+ file->name,
+ type);
+
+ g_file_info_set_size (info,
+ archive_entry_size (entry));
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, type == G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+
+ /* FIXME: add info for these
+dev_t archive_entry_dev(struct archive_entry *);
+dev_t archive_entry_devmajor(struct archive_entry *);
+dev_t archive_entry_devminor(struct archive_entry *);
+void archive_entry_fflags(struct archive_entry *,
+ unsigned long *set, unsigned long *clear);
+const char *archive_entry_fflags_text(struct archive_entry *);
+gid_t archive_entry_gid(struct archive_entry *);
+const char *archive_entry_gname(struct archive_entry *);
+const char *archive_entry_hardlink(struct archive_entry *);
+ino_t archive_entry_ino(struct archive_entry *);
+mode_t archive_entry_mode(struct archive_entry *);
+unsigned int archive_entry_nlink(struct archive_entry *);
+dev_t archive_entry_rdev(struct archive_entry *);
+dev_t archive_entry_rdevmajor(struct archive_entry *);
+dev_t archive_entry_rdevminor(struct archive_entry *);
+uid_t archive_entry_uid(struct archive_entry *);
+const char *archive_entry_uname(struct archive_entry *);
+ */
+
+ /* FIXME: do ACLs */
+}
+
+static void
+fixup_dirs (ArchiveFile *file)
+{
+ GSList *l;
+
+ if (file->info == NULL)
+ {
+ GFileInfo *info = g_file_info_new ();
+
+ file->info = info;
+ g_file_info_set_name (info, file->name);
+ gvfs_file_info_populate_default (info,
+ file->name,
+ G_FILE_TYPE_DIRECTORY);
+ }
+
+ for (l = file->children; l != NULL; l = l->next)
+ fixup_dirs (l->data);
+}
+
+static void
+create_file_tree (GVfsBackendArchive *ba, GVfsJob *job)
+{
+ GVfsArchive *archive;
+ struct archive_entry *entry;
+ int result;
+
+ archive = gvfs_archive_new (ba, job);
+
+ g_assert (ba->files != NULL);
+
+ do
+ {
+ result = archive_read_next_header (archive->archive, &entry);
+ if (result >= ARCHIVE_WARN && result <= ARCHIVE_OK)
+ {
+ if (result < ARCHIVE_OK) {
+ DEBUG ("archive_read_next_header: result = %d, error = '%s'\n", result, archive_error_string (archive->archive));
+ archive_set_error (archive->archive, ARCHIVE_OK, "No error");
+ archive_clear_error (archive->archive);
+ }
+
+ ArchiveFile *file = archive_file_get_from_path (ba->files,
+ archive_entry_pathname (entry),
+ TRUE);
+ /* Don't set info for root */
+ if (file != ba->files)
+ archive_file_set_info_from_entry (file, entry);
+ archive_read_data_skip (archive->archive);
+ }
+ }
+ while (result != ARCHIVE_FATAL && result != ARCHIVE_EOF);
+
+ fixup_dirs (ba->files);
+
+ gvfs_archive_finish (archive);
+}
+
+static void
+archive_file_free (ArchiveFile *file)
+{
+ g_slist_foreach (file->children, (GFunc) archive_file_free, NULL);
+ g_slist_free (file->children);
+ if (file->info)
+ g_object_unref (file->info);
+ g_free (file->name);
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendArchive *archive = G_VFS_BACKEND_ARCHIVE (backend);
+ const char *host, *file;
+ GFileInfo *info;
+ GIcon *icon;
+ char *filename, *s;
+ GError *error = NULL;
+
+ host = g_mount_spec_get (mount_spec, "host");
+ file = g_mount_spec_get (mount_spec, "file");
+ if (host == NULL &&
+ file == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("No hostname specified"));
+ return;
+ }
+
+ if (host != NULL)
+ {
+ filename = g_uri_unescape_string (host, NULL);
+ if (filename == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+
+ archive->file = g_file_new_for_commandline_arg (filename);
+ g_free (filename);
+ }
+ else
+ archive->file = g_file_new_for_commandline_arg (file);
+
+ DEBUG ("Trying to mount %s\n", g_file_get_uri (archive->file));
+
+ info = g_file_query_info (archive->file,
+ "*",
+ G_FILE_QUERY_INFO_NONE,
+ G_VFS_JOB (job)->cancellable,
+ &error);
+ if (info == NULL)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job),
+ error);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+
+ /* FIXME: check if this file is an archive */
+
+ filename = g_file_get_uri (archive->file);
+ DEBUG ("mounted %s\n", filename);
+ s = g_uri_escape_string (filename, NULL, FALSE);
+ mount_spec = g_mount_spec_new ("archive");
+ g_mount_spec_set (mount_spec, "host", s);
+ g_free (s);
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+
+ g_vfs_backend_set_display_name (backend, g_file_info_get_display_name (info));
+
+ icon = g_file_info_get_icon (info);
+
+ g_vfs_backend_set_icon_name (backend, MOUNT_ICON_NAME);
+
+ create_root_file (archive);
+ create_file_tree (archive, G_VFS_JOB (job));
+ g_object_unref (info);
+}
+
+static void
+do_unmount (GVfsBackend *backend,
+ GVfsJobUnmount *job)
+{
+ GVfsBackendArchive *ba = G_VFS_BACKEND_ARCHIVE (backend);
+
+ g_object_unref (ba->file);
+ archive_file_free (ba->files);
+ ba->files = NULL;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_open_for_read (GVfsBackend * backend,
+ GVfsJobOpenForRead *job,
+ const char * filename)
+{
+ GVfsBackendArchive *ba = G_VFS_BACKEND_ARCHIVE (backend);
+ GVfsArchive *archive;
+ struct archive_entry *entry;
+ int result;
+ ArchiveFile *file;
+
+ file = archive_file_find (ba, filename);
+ if (file == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ return;
+ }
+
+ if (g_file_info_get_file_type (file->info) == G_FILE_TYPE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+ return;
+ }
+
+ archive = gvfs_archive_new (ba, G_VFS_JOB (job));
+
+ do
+ {
+ result = archive_read_next_header (archive->archive, &entry);
+ if (result >= ARCHIVE_WARN && result <= ARCHIVE_OK)
+ {
+ if (result < ARCHIVE_OK) {
+ DEBUG ("do_open_for_read: result = %d, error = '%s'\n", result, archive_error_string (archive->archive));
+ archive_set_error (archive->archive, ARCHIVE_OK, "No error");
+ archive_clear_error (archive->archive);
+ }
+
+ if (g_str_equal (archive_entry_pathname (entry), filename + 1))
+ {
+ /* SUCCESS */
+ g_vfs_job_open_for_read_set_handle (job, archive);
+ g_vfs_job_open_for_read_set_can_seek (job, FALSE);
+ gvfs_archive_pop_job (archive);
+ return;
+ }
+ else
+ archive_read_data_skip (archive->archive);
+ }
+ }
+ while (result != ARCHIVE_FATAL && result != ARCHIVE_EOF);
+
+ if (!gvfs_archive_in_error (archive))
+ {
+ g_set_error_literal (&archive->error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ }
+ gvfs_archive_finish (archive);
+}
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GVfsArchive *archive = handle;
+
+ gvfs_archive_push_job (archive, G_VFS_JOB (job));
+ gvfs_archive_finish (archive);
+}
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GVfsArchive *archive = handle;
+ gssize bytes_read;
+
+ gvfs_archive_push_job (archive, G_VFS_JOB (job));
+ bytes_read = archive_read_data (archive->archive, buffer, bytes_requested);
+ if (bytes_read >= 0)
+ g_vfs_job_read_set_size (job, bytes_read);
+ gvfs_archive_pop_job (archive);
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GVfsBackendArchive *ba = G_VFS_BACKEND_ARCHIVE (backend);
+ ArchiveFile *file;
+
+ file = archive_file_find (ba, filename);
+ if (file == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ return;
+ }
+
+ if (!(flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
+ g_warning ("FIXME: follow symlinks");
+
+ g_file_info_copy_into (file->info, info);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendArchive *ba = G_VFS_BACKEND_ARCHIVE (backend);
+ ArchiveFile *file;
+ GSList *walk;
+
+ file = archive_file_find (ba, filename);
+ if (file == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ return;
+ }
+
+ if (g_file_info_get_file_type (file->info) != G_FILE_TYPE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ return;
+ }
+
+ if (!(flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
+ g_warning ("FIXME: follow symlinks");
+
+ for (walk = file->children; walk; walk = walk->next)
+ {
+ GFileInfo *info = g_file_info_dup (((ArchiveFile *) walk->data)->info);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+ g_vfs_job_enumerate_done (job);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+static void
+g_vfs_backend_archive_class_init (GVfsBackendArchiveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_archive_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->unmount = do_unmount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->close_read = do_close_read;
+ backend_class->read = do_read;
+ backend_class->enumerate = do_enumerate;
+ backend_class->query_info = do_query_info;
+ backend_class->try_query_fs_info = try_query_fs_info;
+}
diff --git a/trunk/daemon/gvfsbackendarchive.h b/trunk/daemon/gvfsbackendarchive.h
new file mode 100644
index 00000000..14526ffc
--- /dev/null
+++ b/trunk/daemon/gvfsbackendarchive.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_ARCHIVE_H__
+#define __G_VFS_BACKEND_ARCHIVE_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_ARCHIVE (g_vfs_backend_archive_get_type ())
+#define G_VFS_BACKEND_ARCHIVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_ARCHIVE, GVfsBackendArchive))
+#define G_VFS_BACKEND_ARCHIVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_ARCHIVE, GVfsBackendArchiveClass))
+#define G_VFS_IS_BACKEND_ARCHIVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_ARCHIVE))
+#define G_VFS_IS_BACKEND_ARCHIVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_ARCHIVE))
+#define G_VFS_BACKEND_ARCHIVE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_ARCHIVE, GVfsBackendArchiveClass))
+
+typedef struct _GVfsBackendArchive GVfsBackendArchive;
+typedef struct _GVfsBackendArchiveClass GVfsBackendArchiveClass;
+
+struct _GVfsBackendArchiveClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_archive_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_ARCHIVE_H__ */
diff --git a/trunk/daemon/gvfsbackendburn.c b/trunk/daemon/gvfsbackendburn.c
new file mode 100644
index 00000000..eddb47a1
--- /dev/null
+++ b/trunk/daemon/gvfsbackendburn.c
@@ -0,0 +1,1047 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+#include "gvfsbackendburn.h"
+#include "gvfsmonitor.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobmountmountable.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobdelete.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsdaemonprotocol.h"
+
+/* TODO:
+ * Change notification
+ *
+ */
+
+typedef enum {
+ VIRTUAL_NODE_FILE,
+ VIRTUAL_NODE_DIRECTORY
+} VirtualNodeType;
+
+typedef struct {
+ char *filename;
+ VirtualNodeType type;
+
+ /* for files: */
+ char *backing_file; /* local filename */
+ gboolean owned_file;
+
+ GList *subscriptions;
+
+ /* for directories: */
+ GList *children;
+ volatile gint ref_count;
+} VirtualNode;
+
+struct _GVfsBackendBurn
+{
+ GVfsBackend parent_instance;
+
+ char *tempdir;
+
+ VirtualNode *root_node;
+
+ GMountSpec *mount_spec;
+};
+
+G_DEFINE_TYPE (GVfsBackendBurn, g_vfs_backend_burn, G_VFS_TYPE_BACKEND)
+
+
+static void virtual_node_unref (VirtualNode *node);
+
+static VirtualNode *
+virtual_node_new (const char *filename,
+ VirtualNodeType type)
+{
+ VirtualNode *node;
+
+ node = g_slice_new0 (VirtualNode);
+ node->filename = g_strdup (filename);
+ node->type = type;
+ node->ref_count = 1;
+
+ return node;
+}
+
+static void
+virtual_node_free (VirtualNode *node,
+ gboolean deep)
+{
+ GList *l;
+
+ g_free (node->filename);
+
+ switch (node->type)
+ {
+ case VIRTUAL_NODE_FILE:
+ if (node->backing_file != NULL)
+ {
+ if (node->owned_file)
+ g_unlink (node->backing_file);
+ g_free (node->backing_file);
+ }
+ break;
+ case VIRTUAL_NODE_DIRECTORY:
+ if (deep)
+ {
+ for (l = node->children; l != NULL; l = l->next)
+ virtual_node_unref ((VirtualNode *)l->data);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ /*
+ while ((l = g_list_first (node->subscriptions)) != NULL) {
+ MappingSubscription *sub = l->data;
+ virtual_node_remove_subscription (node, sub);
+ }
+ */
+
+ g_slice_free (VirtualNode, node);
+}
+
+static void
+virtual_node_unref (VirtualNode *node)
+{
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (node->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&node->ref_count))
+ virtual_node_free (node, TRUE);
+}
+
+static G_GNUC_UNUSED VirtualNode *
+virtual_node_ref (VirtualNode *node)
+{
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (node->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&node->ref_count);
+ return node;
+}
+
+
+static VirtualNode *
+virtual_dir_lookup (VirtualNode *dir,
+ const char *filename)
+{
+ GList *l;
+ VirtualNode *node;
+
+ g_assert (dir->type == VIRTUAL_NODE_DIRECTORY);
+
+ for (l = dir->children; l != NULL; l = l->next)
+ {
+ node = l->data;
+
+ if (strcmp (node->filename, filename) == 0)
+ return node;
+ }
+
+ return NULL;
+}
+
+static VirtualNode *
+virtual_node_lookup (VirtualNode *root_dir,
+ const char *path,
+ VirtualNode **parent)
+{
+ char *copy, *next, *copy_orig;
+ VirtualNode *node;
+
+ copy_orig = g_strdup (path);
+ copy = copy_orig;
+
+ if (parent != NULL)
+ *parent = NULL;
+
+ node = root_dir;
+
+ while (copy != NULL)
+ {
+ /* Skip initial/multiple slashes */
+ while (G_IS_DIR_SEPARATOR (*copy))
+ ++copy;
+
+ if (*copy == 0)
+ break;
+
+ next = strchr (copy, G_DIR_SEPARATOR);
+ if (next)
+ {
+ *next = 0;
+ next++;
+ }
+
+ if (node->type != VIRTUAL_NODE_DIRECTORY)
+ {
+ /* Found a file in the middle of the path */
+ node = NULL;
+ break;
+ }
+
+ if (parent != NULL)
+ *parent = node;
+
+ node = virtual_dir_lookup (node, copy);
+ if (node == NULL)
+ break;
+
+ copy = next;
+ }
+
+ g_free (copy_orig);
+
+ return node;
+}
+
+static VirtualNode *
+virtual_mkdir (VirtualNode *node,
+ const char *name)
+{
+ VirtualNode *subdir;
+
+ g_assert (node->type == VIRTUAL_NODE_DIRECTORY);
+
+ if (virtual_dir_lookup (node, name) != NULL)
+ return NULL;
+
+ subdir = virtual_node_new (name, VIRTUAL_NODE_DIRECTORY);
+
+ /* list takes ownership of ref */
+ node->children = g_list_append (node->children, subdir);
+
+ return subdir;
+}
+
+static void
+virtual_unlink (VirtualNode *dir,
+ VirtualNode *node)
+{
+ g_assert (dir->type == VIRTUAL_NODE_DIRECTORY);
+
+ dir->children = g_list_remove (dir->children, node);
+ virtual_node_unref (node);
+}
+
+static VirtualNode *
+virtual_create (GVfsBackendBurn *backend,
+ VirtualNode *dir,
+ const char *name,
+ const char *backing_file)
+{
+ VirtualNode *file;
+ char *template;
+ int fd;
+
+ g_assert (dir->type == VIRTUAL_NODE_DIRECTORY);
+
+ if (virtual_dir_lookup (dir, name) != NULL)
+ return NULL;
+
+ file = virtual_node_new (name, VIRTUAL_NODE_FILE);
+
+ if (backing_file != NULL)
+ {
+ file->backing_file = g_strdup (backing_file);
+ file->owned_file = FALSE;
+ }
+ else
+ {
+ template = g_build_filename (backend->tempdir, "file.XXXXXX", NULL);
+
+ fd = g_mkstemp (template);
+ if (fd < 0)
+ {
+ g_free (template);
+ virtual_node_unref (file);
+ return NULL;
+
+ }
+ close (fd);
+ g_unlink (template);
+
+ file->backing_file = template;
+ file->owned_file = TRUE;
+ }
+
+ /* list takes ownership of ref */
+ dir->children = g_list_append (dir->children, file);
+
+ return file;
+}
+
+static void
+g_vfs_backend_burn_finalize (GObject *object)
+{
+ GVfsBackendBurn *backend;
+
+ backend = G_VFS_BACKEND_BURN (object);
+
+ g_mount_spec_unref (backend->mount_spec);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_burn_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_burn_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_burn_init (GVfsBackendBurn *burn_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (burn_backend);
+ GMountSpec *mount_spec;
+
+ /* Translators: This is the name of the backend */
+ g_vfs_backend_set_display_name (backend, _("Burn"));
+ g_vfs_backend_set_icon_name (backend, "computer");
+ g_vfs_backend_set_user_visible (backend, FALSE);
+
+ mount_spec = g_mount_spec_new ("burn");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ burn_backend->mount_spec = mount_spec;
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendBurn *burn_backend = G_VFS_BACKEND_BURN (backend);
+ char *tempdir, *filename;
+ char *dir;
+
+ filename = g_strdup_printf ("virtual-%s.XXXXXX", g_get_user_name ());
+ tempdir = g_build_filename (g_get_tmp_dir (), filename, NULL);
+ g_free (filename);
+
+ dir = mkdtemp (tempdir);
+ if (dir == NULL)
+ {
+ g_free (tempdir);
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to create temporary directory"));
+ return TRUE;
+ }
+
+ burn_backend->tempdir = dir;
+ burn_backend->root_node =
+ virtual_node_new (NULL, VIRTUAL_NODE_DIRECTORY);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+static gboolean
+try_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ char *dirname, *basename;
+ VirtualNode *file, *dir;
+
+ dirname = g_path_get_dirname (filename);
+ dir = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, dirname, NULL);
+ g_free (dirname);
+
+ if (dir == NULL ||
+ dir->type != VIRTUAL_NODE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ basename = g_path_get_basename (filename);
+ file = virtual_dir_lookup (dir, basename);
+ g_free (basename);
+ if (file == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ if (file->type == VIRTUAL_NODE_DIRECTORY &&
+ file->children != NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_EMPTY,
+ _("Directory not empty"));
+ return TRUE;
+ }
+
+ virtual_unlink (dir, file);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ VirtualNode *node;
+ GFileInputStream *stream;
+ GFile *file;
+ GError *error;
+
+ node = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, filename, NULL);
+ if (node == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ if (node->type == VIRTUAL_NODE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("Can't copy file over directory"));
+ return TRUE;
+ }
+
+ file = g_file_new_for_path (node->backing_file);
+
+ error = NULL;
+ stream = g_file_read (file, G_VFS_JOB (job)->cancellable, &error);
+ g_object_unref (file);
+
+ if (stream)
+ {
+ g_vfs_job_open_for_read_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
+ g_vfs_job_open_for_read_set_handle (job, stream);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+
+ return TRUE;
+}
+
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+ gssize s;
+
+ error = NULL;
+ s = g_input_stream_read (G_INPUT_STREAM(stream),
+ buffer, bytes_requested,
+ G_VFS_JOB (job)->cancellable, &error);
+ if (s >= 0)
+ {
+ g_vfs_job_read_set_size (job, s);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+do_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+
+ error = NULL;
+ if (g_seekable_seek (G_SEEKABLE (stream), offset, type,
+ G_VFS_JOB (job)->cancellable, &error))
+ {
+ g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (stream)));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle _handle)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+
+ error = NULL;
+ if (g_input_stream_close (G_INPUT_STREAM(stream),
+ G_VFS_JOB (job)->cancellable, &error))
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+
+ g_object_unref (stream);
+}
+
+static char *
+make_valid_utf8 (const char *name)
+{
+ GString *string;
+ const gchar *remainder, *invalid;
+ gint remaining_bytes, valid_bytes;
+
+ string = NULL;
+ remainder = name;
+ remaining_bytes = strlen (name);
+
+ while (remaining_bytes != 0)
+ {
+ if (g_utf8_validate (remainder, remaining_bytes, &invalid))
+ break;
+ valid_bytes = invalid - remainder;
+
+ if (string == NULL)
+ string = g_string_sized_new (remaining_bytes);
+
+ g_string_append_len (string, remainder, valid_bytes);
+ /* append U+FFFD REPLACEMENT CHARACTER */
+ g_string_append (string, "\357\277\275");
+
+ remaining_bytes -= valid_bytes + 1;
+ remainder = invalid + 1;
+ }
+
+ if (string == NULL)
+ return g_strdup (name);
+
+ g_string_append (string, remainder);
+
+ g_warn_if_fail (g_utf8_validate (string->str, -1, NULL));
+
+ return g_string_free (string, FALSE);
+}
+
+
+static void
+file_info_from_node (VirtualNode *node,
+ GFileInfo *info,
+ const char *attributes)
+{
+ GIcon *icon;
+ GFile *file;
+ GFileInfo *file_info;
+
+ if (node->type == VIRTUAL_NODE_DIRECTORY)
+ {
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_content_type (info, "inode/directory");
+ }
+ else
+ {
+ file = g_file_new_for_path (node->backing_file);
+ file_info = g_file_query_info (file,
+ attributes,
+ 0, /* Always follow symlinks */
+ NULL, NULL);
+ if (file_info)
+ {
+ g_file_info_copy_into (file_info, info);
+ g_object_unref (file_info);
+ }
+
+ g_file_info_set_attribute_byte_string (info,
+ "burn::backing-file",
+ node->backing_file);
+ }
+
+ if (node->filename != NULL)
+ {
+ char *utf8;
+
+ g_file_info_set_name (info, node->filename);
+ /* Ensure display name is utf8 */
+ utf8 = make_valid_utf8 (node->filename);
+ g_file_info_set_display_name (info, utf8);
+ g_free (utf8);
+ }
+ else
+ {
+ g_file_info_set_name (info, "/");
+ /* Translators: this is the display name of the backend */
+ g_file_info_set_display_name (info, _("CD/DVD Creator"));
+ }
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ VirtualNode *node, *child;
+ GFileInfo *info;
+ GList *l;
+
+ node = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, filename, NULL);
+
+ if (node == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ if (node->type != VIRTUAL_NODE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ return TRUE;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ for (l = node->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ info = g_file_info_new ();
+ file_info_from_node (child, info, job->attributes);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ g_vfs_job_enumerate_done (job);
+
+ return TRUE;
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ VirtualNode *node;
+
+ node = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, filename, NULL);
+
+ if (node == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ file_info_from_node (node, info, job->attributes);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static gboolean
+try_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ char *dirname, *basename;
+ VirtualNode *file, *dir;
+
+ dirname = g_path_get_dirname (filename);
+ dir = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, dirname, NULL);
+ g_free (dirname);
+
+ if (dir == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ basename = g_path_get_basename (filename);
+ file = virtual_dir_lookup (dir, basename);
+ if (file != NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("File exists"));
+ g_free (basename);
+ return TRUE;
+ }
+
+ file = virtual_mkdir (dir, basename);
+ g_free (basename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static gboolean
+try_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ VirtualNode *node, *dir;
+ char *target_path;
+ char *dirname;
+
+ node = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, filename, &dir);
+ if (node == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ if (virtual_dir_lookup (dir, display_name) != NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("File exists"));
+ return TRUE;
+ }
+
+ /* We use UTF8 for filenames */
+ g_free (node->filename);
+ node->filename = g_strdup (display_name);
+
+ dirname = g_path_get_dirname (filename);
+ target_path = g_build_filename (dirname, display_name, NULL);
+ g_vfs_job_set_display_name_set_new_path (job, target_path);
+ g_free (dirname);
+ g_free (target_path);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+
+}
+
+static gboolean
+try_push (GVfsBackend *backend,
+ GVfsJobPush *job,
+ const char *destination,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ VirtualNode *file, *dir;
+ struct stat stat_buf;
+ char *dirname, *basename;
+
+ if (remove_source)
+ {
+ /* Fallback to copy & delete for now, fix that up later */
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return TRUE;
+ }
+
+ if (g_stat (local_path, &stat_buf) == -1)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "%s", g_strerror (errsv));
+ return TRUE;
+ }
+
+ dirname = g_path_get_dirname (destination);
+ dir = virtual_node_lookup (G_VFS_BACKEND_BURN (backend)->root_node, dirname, NULL);
+ g_free (dirname);
+ file = NULL;
+
+ if (dir == NULL)
+ {
+ /* Parent of created file doesn't exist */
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory in target path"));
+ return TRUE;
+ }
+
+ basename = g_path_get_basename (destination);
+ file = virtual_dir_lookup (dir, basename);
+ g_free (basename);
+
+ if (S_ISDIR (stat_buf.st_mode))
+ {
+ /* The source is a directory, don't fail with WOULD_RECURSE immediately,
+ * as that is less useful to the app. Better check for errors on the
+ * target instead.
+ */
+
+ if (file != NULL)
+ {
+ if (flags & G_FILE_COPY_OVERWRITE)
+ {
+ if (file->type == VIRTUAL_NODE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_WOULD_MERGE,
+ _("Can't copy directory over directory"));
+ return TRUE;
+ }
+ /* continue to would_recurse error */
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_EXISTS,
+ _("Target file exists"));
+ return TRUE;
+ }
+ }
+
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
+ _("Can't recursively copy directory"));
+ return TRUE;
+ }
+
+ if (file != NULL)
+ {
+ if (flags & G_FILE_COPY_OVERWRITE)
+ {
+ if (file->type == VIRTUAL_NODE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("Can't copy file over directory"));
+ return TRUE;
+ }
+ else
+ {
+ g_assert (file->type == VIRTUAL_NODE_FILE);
+ if (file->owned_file)
+ g_unlink (file->backing_file);
+ g_free (file->backing_file);
+ file->owned_file = FALSE;
+ file->backing_file = g_strdup (local_path);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_EXISTS,
+ _("File exists"));
+ return TRUE;
+ }
+ }
+ else
+ {
+ basename = g_path_get_basename (destination);
+ file = virtual_create (G_VFS_BACKEND_BURN (backend),
+ dir,
+ basename,
+ local_path);
+ g_free (basename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+ }
+}
+
+static gboolean
+try_create_dir_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+ return TRUE;
+}
+
+static gboolean
+try_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ VirtualNode *source_node, *dest_node, *root_node, *source_dir, *dest_dir;
+
+ root_node = G_VFS_BACKEND_BURN (backend)->root_node;
+
+ source_node = virtual_node_lookup (root_node, source, &source_dir);
+ if (source_node == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ dest_node = virtual_node_lookup (root_node, destination, &dest_dir);
+ if (dest_node != NULL)
+ {
+ if (flags & G_FILE_COPY_OVERWRITE)
+ {
+ if (dest_node->type == VIRTUAL_NODE_DIRECTORY)
+ {
+ if (source_node->type == VIRTUAL_NODE_DIRECTORY)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_WOULD_MERGE,
+ _("File exists"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("File exists"));
+ return TRUE;
+ }
+ else
+ virtual_unlink (dest_dir, dest_node);
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("File exists"));
+ return TRUE;
+ }
+ }
+ else if (dest_dir == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ return TRUE;
+ }
+
+ g_free (source_node->filename);
+ source_node->filename = g_path_get_basename (destination);
+
+ if (source_dir != dest_dir)
+ {
+ source_dir->children = g_list_remove (source_dir->children, source_node);
+ dest_dir->children = g_list_append (dest_dir->children, source_node);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_burn_class_init (GVfsBackendBurnClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_burn_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_create_dir_monitor = try_create_dir_monitor;
+ backend_class->try_make_directory = try_make_directory;
+ backend_class->try_set_display_name = try_set_display_name;
+ backend_class->try_push = try_push;
+ backend_class->try_delete = try_delete;
+ backend_class->try_move = try_move;
+ backend_class->read = do_read;
+ backend_class->seek_on_read = do_seek_on_read;
+ backend_class->close_read = do_close_read;
+}
diff --git a/trunk/daemon/gvfsbackendburn.h b/trunk/daemon/gvfsbackendburn.h
new file mode 100644
index 00000000..42b26f7d
--- /dev/null
+++ b/trunk/daemon/gvfsbackendburn.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_BURN_H__
+#define __G_VFS_BACKEND_BURN_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_BURN (g_vfs_backend_burn_get_type ())
+#define G_VFS_BACKEND_BURN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_BURN, GVfsBackendBurn))
+#define G_VFS_BACKEND_BURN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_BURN, GVfsBackendBurnClass))
+#define G_VFS_IS_BACKEND_BURN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_BURN))
+#define G_VFS_IS_BACKEND_BURN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_BURN))
+#define G_VFS_BACKEND_BURN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_BURN, GVfsBackendBurnClass))
+
+typedef struct _GVfsBackendBurn GVfsBackendBurn;
+typedef struct _GVfsBackendBurnClass GVfsBackendBurnClass;
+
+struct _GVfsBackendBurnClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_burn_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_BURN_H__ */
diff --git a/trunk/daemon/gvfsbackendcdda.c b/trunk/daemon/gvfsbackendcdda.c
new file mode 100644
index 00000000..c97aa447
--- /dev/null
+++ b/trunk/daemon/gvfsbackendcdda.c
@@ -0,0 +1,1035 @@
+/* GVFS cdrom audio file system driver
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+/* NOTE: since we link the libcdio libs (GPLv2) into our process space
+ * the combined work is GPLv2. This source file, however, is LGPLv2+.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <libhal.h>
+#include <dbus/dbus.h>
+
+#include "gvfsbackendcdda.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+
+#define DO_NOT_WANT_PARANOIA_COMPATIBILITY
+#include <cdio/paranoia.h>
+#include <cdio/cdio.h>
+
+/* TODO:
+ *
+ * - GVFS integration
+ * - g_vfs_backend_set_display_name() needs to work post mount
+ *
+ * - Metadata
+ * - Use CD-Text to read metadata from the physical disc
+ * - http://en.wikipedia.org/wiki/CD-Text
+ * - libcdio can do this
+ * - Use Musicbrainz to read metadata from the net
+ * - libmusicbrainz appear to be a dead-end: http://musicbrainz.org/doc/libmusicbrainz
+ * - Need to provide some UI for configuring musicbrainz; think proxy, local server,
+ * lockdown (secure facilities don't want us to randomly connect to the Interwebs)
+ * - Ideally use libjuicer for all this
+ * - however it is currently private to sound-juicer and brings in GTK+, gnome-vfs, gconf...
+ * - Use metadata for file names and display_name of our Mount (using g_vfs_backend_set_display_name())
+ * - Also encode metadata in the WAV header so transcoding to Vorbis or MP3 Just Works(tm)
+ * - This is already done; see create_header() in this file
+ * - see thread on gtk-devel-list for a plan
+ *
+ * - Scratched discs / error conditions from paranoia
+ * - Need to handle this better... ideally caller passes a flag when opening the file to
+ * specify whether he wants us to try hard to get the hard result (ripping) or whether
+ * he's fine with some noise (playback)
+ *
+ * - Sector cache? Might be useful to maintain a cache of previously read sectors
+ */
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+typedef struct {
+ char *artist;
+ char *title;
+ int duration; /* Duration in seconds */
+} GVfsBackendCddaTrack;
+
+struct _GVfsBackendCdda
+{
+ GVfsBackend parent_instance;
+
+ DBusConnection *dbus_connection;
+ LibHalContext *hal_ctx;
+ char *hal_udi;
+
+ guint64 size;
+
+ char *device_path;
+ cdrom_drive_t *drive;
+ int num_open_files;
+
+ /* Metadata from CD-Text */
+ char *album_title;
+ char *album_artist;
+ char *genre;
+ GList *tracks; /* a GList of GVfsBackendCddaTrack */
+};
+
+G_DEFINE_TYPE (GVfsBackendCdda, g_vfs_backend_cdda, G_VFS_TYPE_BACKEND)
+
+static void
+release_device (GVfsBackendCdda *cdda_backend)
+{
+ g_free (cdda_backend->device_path);
+ cdda_backend->device_path = NULL;
+
+ if (cdda_backend->drive != NULL)
+ {
+ cdio_cddap_close (cdda_backend->drive);
+ cdda_backend->drive = NULL;
+ }
+}
+
+/* Metadata related functions */
+static void
+track_free (GVfsBackendCddaTrack *track)
+{
+ if (track == NULL)
+ return;
+ g_free (track->artist);
+ g_free (track->title);
+}
+
+static void
+release_metadata (GVfsBackendCdda *cdda_backend)
+{
+ g_free (cdda_backend->album_title);
+ cdda_backend->album_title = NULL;
+ g_free (cdda_backend->album_artist);
+ cdda_backend->album_artist = NULL;
+ g_free (cdda_backend->genre);
+ cdda_backend->genre = NULL;
+ g_list_foreach (cdda_backend->tracks, (GFunc) track_free, NULL);
+ g_list_free (cdda_backend->tracks);
+ cdda_backend->tracks = NULL;
+}
+
+static void
+fetch_metadata (GVfsBackendCdda *cdda_backend)
+{
+ CdIo *cdio;
+ track_t cdtrack, last_cdtrack;
+ const cdtext_t *cdtext;
+
+ cdio = cdio_open (cdda_backend->device_path, DRIVER_UNKNOWN);
+ if (!cdio)
+ return;
+
+ cdtext = cdio_get_cdtext(cdio, 0);
+ if (cdtext) {
+ cdda_backend->album_title = g_strdup (cdtext_get (CDTEXT_TITLE, cdtext));
+ cdda_backend->album_artist = g_strdup (cdtext_get (CDTEXT_PERFORMER, cdtext));
+ cdda_backend->genre = g_strdup (cdtext_get (CDTEXT_GENRE, cdtext));
+ }
+
+ cdtrack = cdio_get_first_track_num(cdio);
+ last_cdtrack = cdtrack + cdio_get_num_tracks(cdio);
+
+ for ( ; cdtrack < last_cdtrack; cdtrack++ ) {
+ GVfsBackendCddaTrack *track;
+ track = g_new0 (GVfsBackendCddaTrack, 1);
+ cdtext = cdio_get_cdtext(cdio, cdtrack);
+ if (cdtext) {
+ track->title = g_strdup (cdtext_get (CDTEXT_TITLE, cdtext));
+ track->artist = g_strdup (cdtext_get (CDTEXT_PERFORMER, cdtext));
+ }
+ track->duration = cdio_get_track_sec_count (cdio, cdtrack) / CDIO_CD_FRAMES_PER_SEC;
+
+ cdda_backend->tracks = g_list_append (cdda_backend->tracks, track);
+ }
+
+ cdio_destroy (cdio);
+}
+
+static void
+find_udi_for_device (GVfsBackendCdda *cdda_backend)
+{
+ int num_devices;
+ char **devices;
+ int n;
+
+ cdda_backend->hal_udi = NULL;
+
+ devices = libhal_manager_find_device_string_match (cdda_backend->hal_ctx,
+ "block.device",
+ cdda_backend->device_path,
+ &num_devices,
+ NULL);
+ if (devices != NULL)
+ {
+ for (n = 0; n < num_devices && cdda_backend->hal_udi == NULL; n++)
+ {
+ char *udi = devices[n];
+ LibHalPropertySet *ps;
+
+ ps = libhal_device_get_all_properties (cdda_backend->hal_ctx, udi, NULL);
+ if (ps != NULL)
+ {
+ if (libhal_ps_get_bool (ps, "block.is_volume"))
+ {
+ cdda_backend->hal_udi = g_strdup (udi);
+ cdda_backend->size = libhal_ps_get_uint64 (ps, "volume.size");
+ }
+ }
+
+ libhal_free_property_set (ps);
+ }
+ }
+ libhal_free_string_array (devices);
+
+ /*g_warning ("found udi '%s'", cdda_backend->hal_udi);*/
+}
+
+static void
+_hal_device_removed (LibHalContext *hal_ctx, const char *udi)
+{
+ GVfsBackendCdda *cdda_backend;
+
+ cdda_backend = G_VFS_BACKEND_CDDA (libhal_ctx_get_user_data (hal_ctx));
+
+ if (cdda_backend->hal_udi != NULL && strcmp (udi, cdda_backend->hal_udi) == 0)
+ {
+ /*g_warning ("we have been removed!");*/
+ /* TODO: need a cleaner way to force unmount ourselves */
+ exit (1);
+ }
+}
+
+static void
+g_vfs_backend_cdda_finalize (GObject *object)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (object);
+
+ //g_warning ("finalizing %p", object);
+
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_cdda_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_cdda_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_cdda_init (GVfsBackendCdda *cdda_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (cdda_backend);
+ GMountSpec *mount_spec;
+ char *x_content_types[] = {"x-content/audio-cdda", NULL};
+
+ //g_warning ("initing %p", cdda_backend);
+
+ g_vfs_backend_set_display_name (backend, "cdda");
+ g_vfs_backend_set_x_content_types (backend, x_content_types);
+ // TODO: HMM: g_vfs_backend_set_user_visible (backend, FALSE);
+
+ mount_spec = g_mount_spec_new ("cdda");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ char *fuse_name;
+ char *display_name;
+ const char *host;
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+ GError *error = NULL;
+ GMountSpec *cdda_mount_spec;
+ DBusError dbus_error;
+
+ //g_warning ("do_mount %p", cdda_backend);
+
+ /* setup libhal */
+
+ dbus_error_init (&dbus_error);
+ cdda_backend->dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ dbus_error_free (&dbus_error);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot connect to the system bus"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ cdda_backend->hal_ctx = libhal_ctx_new ();
+ if (cdda_backend->hal_ctx == NULL)
+ {
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot create libhal context"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ _g_dbus_connection_integrate_with_main (cdda_backend->dbus_connection);
+ libhal_ctx_set_dbus_connection (cdda_backend->hal_ctx, cdda_backend->dbus_connection);
+
+ if (!libhal_ctx_init (cdda_backend->hal_ctx, &dbus_error))
+ {
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ dbus_error_free (&dbus_error);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot initialize libhal"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ libhal_ctx_set_device_removed (cdda_backend->hal_ctx, _hal_device_removed);
+ libhal_ctx_set_user_data (cdda_backend->hal_ctx, cdda_backend);
+
+ /* setup libcdio */
+
+ host = g_mount_spec_get (mount_spec, "host");
+ //g_warning ("host=%s", host);
+ if (host == NULL)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No drive specified"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ return;
+ }
+
+ cdda_backend->device_path = g_strdup_printf ("/dev/%s", host);
+
+ find_udi_for_device (cdda_backend);
+
+ cdda_backend->drive = cdio_cddap_identify (cdda_backend->device_path, 0, NULL);
+ if (cdda_backend->drive == NULL)
+ {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Cannot find drive %s"), cdda_backend->device_path);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ return;
+ }
+
+ fetch_metadata (cdda_backend);
+
+ if (cdio_cddap_open (cdda_backend->drive) != 0)
+ {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Drive %s does not contain audio files"), cdda_backend->device_path);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+ return;
+ }
+
+ /* Translator: %s is the device the disc is inserted into */
+ fuse_name = g_strdup_printf (_("cdda mount on %s"), host);
+ display_name = g_strdup_printf (_("Audio Disc"));
+ g_vfs_backend_set_stable_name (backend, fuse_name);
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+ g_free (fuse_name);
+ g_vfs_backend_set_icon_name (backend, "media-optical-audio");
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ cdda_mount_spec = g_mount_spec_new ("cdda");
+ g_mount_spec_set (cdda_mount_spec, "host", host);
+ g_vfs_backend_set_mount_spec (backend, cdda_mount_spec);
+ g_mount_spec_unref (cdda_mount_spec);
+
+ //g_warning ("mounted %p", cdda_backend);
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ const char *host;
+ GError *error = NULL;
+ GMountSpec *cdda_mount_spec;
+
+ //g_warning ("try_mount %p", backend);
+
+ /* TODO: Hmm.. apparently we have to set the mount spec in
+ * try_mount(); doing it in mount() won't work..
+ */
+ host = g_mount_spec_get (mount_spec, "host");
+ //g_warning ("tm host=%s", host);
+ if (host == NULL)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No drive specified"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return TRUE;
+ }
+
+ cdda_mount_spec = g_mount_spec_new ("cdda");
+ g_mount_spec_set (cdda_mount_spec, "host", host);
+ g_vfs_backend_set_mount_spec (backend, cdda_mount_spec);
+ g_mount_spec_unref (cdda_mount_spec);
+ return FALSE;
+}
+
+
+static void
+do_unmount (GVfsBackend *backend,
+ GVfsJobUnmount *job)
+{
+ GError *error;
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+
+ if (cdda_backend->num_open_files > 0)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_BUSY,
+ ngettext ("File system is busy: %d open file",
+ "File system is busy: %d open files",
+ cdda_backend->num_open_files),
+ cdda_backend->num_open_files);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
+
+ release_device (cdda_backend);
+ release_metadata (cdda_backend);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ //g_warning ("unmounted %p", backend);
+}
+
+/* returns -1 if we couldn't map */
+static int
+get_track_num_from_name (GVfsBackendCdda *cdda_backend, const char *filename)
+{
+ int n;
+ char *basename;
+
+ basename = g_path_get_basename (filename);
+ if (sscanf (basename, "Track %d.wav", &n) == 1)
+ {
+ g_free (basename);
+ return n;
+ }
+
+ return -1;
+}
+
+typedef struct {
+ cdrom_paranoia_t *paranoia;
+
+ long size; /* size of file being read */
+ long header_size; /* size of the header */
+ long content_size; /* size of content after the header */
+
+ long cursor; /* cursor into the file being read */
+
+ long first_sector; /* first sector of raw PCM audio data */
+ long last_sector; /* last sector of raw PCM audio data */
+ long sector_cursor; /* sector we're currently at */
+
+ char *header; /* header payload */
+
+ /* These following two fields are used for caching the last read sector. This
+ * is to avoid seeking back if fewer bytes than whole sector is requested.
+ */
+ long buf_at_sector_num; /* the sector that is cached */
+ char buf_at_sector[CDIO_CD_FRAMESIZE_RAW]; /* the data of the sector */
+
+} ReadHandle;
+
+static void
+free_read_handle (ReadHandle *read_handle)
+{
+ if (read_handle->paranoia != NULL)
+ cdio_paranoia_free (read_handle->paranoia);
+ g_free (read_handle->header);
+ g_free (read_handle);
+}
+
+static char *
+create_header (GVfsBackendCdda *cdda_backend, long *header_size, long content_size)
+{
+ char *artist;
+ char *title;
+ const char *software;
+ size_t artist_len;
+ size_t title_len;
+ size_t software_len;
+ char *header;
+ char *ptr;
+ int var;
+
+ /* See http://www.saettler.com/RIFFMCI/riffmci.html for the spec.
+ *
+ * artist -> IART
+ * title -> INAM
+ * track_number -> ?? (TODO: work with GStreamer people on coordinate with the wavparse plugin)
+ *
+ * software -> ISFT
+ */
+
+
+ //artist = g_strdup ("Homer Simpson");
+ //title = g_strdup ("Simpsons Jail House Rock");
+
+ /* TODO: fill in from metadata */
+ artist = NULL;
+ title = NULL;
+ software = "gvfs-cdda using libcdio " CDIO_VERSION;
+
+ artist_len = 0;
+ title_len = 0;
+
+ /* ensure even length and include room for the chunk */
+ if (artist != NULL)
+ artist_len = 2 * ((strlen (artist) + 2) / 2) + 8;
+ if (title != NULL)
+ title_len = 2 * ((strlen (title) + 2) / 2) + 8;
+ software_len = 2 * ((strlen (software) + 2) / 2) + 8;
+
+ *header_size = 44;
+ *header_size += 12; /* for LIST INFO */
+ *header_size += artist_len;
+ *header_size += title_len;
+ *header_size += software_len;
+ header = g_new0 (char, *header_size);
+
+ ptr = header;
+ memcpy (ptr, "RIFF", 4); ptr += 4;
+ var = content_size + *header_size - 8;
+ memcpy (ptr, &var, 4); ptr += 4;
+ memcpy (ptr, "WAVE", 4); ptr += 4;
+
+ memcpy (ptr, "fmt ", 4); ptr += 4;
+ var = 16;
+ memcpy (ptr, &var, 4); ptr += 4;
+ var = 1;
+ memcpy (ptr, &var, 2); ptr += 2;
+ var = 2;
+ memcpy (ptr, &var, 2); ptr += 2;
+ var = 44100;
+ memcpy (ptr, &var, 4); ptr += 4;
+ var = 44100 * 2 * 2;
+ memcpy (ptr, &var, 4); ptr += 4;
+ var = 4;
+ memcpy (ptr, &var, 2); ptr += 2;
+ var = 16;
+ memcpy (ptr, &var, 2); ptr += 2;
+
+ memcpy (ptr, "LIST", 4); ptr += 4;
+ var = 4 + artist_len + title_len + software_len;
+ memcpy (ptr, &var, 4); ptr += 4;
+ memcpy (ptr, "INFO", 4); ptr += 4;
+
+ if (artist != NULL)
+ {
+ memcpy (ptr, "IART", 4);
+ var = artist_len - 8;
+ memcpy (ptr + 4, &var, 4);
+ strncpy (ptr + 8, artist, artist_len);
+ ptr += artist_len;
+ }
+
+ if (title != NULL)
+ {
+ memcpy (ptr, "INAM", 4);
+ var = title_len - 8;
+ memcpy (ptr + 4, &var, 4);
+ strncpy (ptr + 8, title, title_len);
+ ptr += title_len;
+ }
+
+ memcpy (ptr, "ISFT", 4);
+ var = software_len - 8;
+ memcpy (ptr + 4, &var, 4);
+ strncpy (ptr + 8, software, software_len);
+ ptr += software_len;
+
+ memcpy (ptr, "data", 4); ptr += 4;
+ memcpy (ptr, &content_size, 4); ptr += 4;
+
+ g_free (artist);
+ g_free (title);
+
+ return header;
+}
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ int track_num;
+ GError *error;
+ ReadHandle *read_handle;
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+
+ //g_warning ("open_for_read (%s)", filename);
+
+ read_handle = g_new0 (ReadHandle, 1);
+
+ track_num = get_track_num_from_name (cdda_backend, job->filename);
+ if (track_num == -1)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("No such file %s on drive %s"), job->filename, cdda_backend->device_path);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ free_read_handle (read_handle);
+ return;
+ }
+
+
+ read_handle->first_sector = cdio_cddap_track_firstsector (cdda_backend->drive, track_num);
+ read_handle->last_sector = cdio_cddap_track_lastsector (cdda_backend->drive, track_num);
+ read_handle->sector_cursor = -1;
+
+ read_handle->cursor = 0;
+ read_handle->buf_at_sector_num = -1;
+ read_handle->content_size = ((read_handle->last_sector - read_handle->first_sector) + 1) * CDIO_CD_FRAMESIZE_RAW;
+
+ read_handle->header = create_header (cdda_backend, &(read_handle->header_size), read_handle->content_size);
+ read_handle->size = read_handle->header_size + read_handle->content_size;
+
+ read_handle->paranoia = cdio_paranoia_init (cdda_backend->drive);
+ cdio_paranoia_modeset (read_handle->paranoia, PARANOIA_MODE_DISABLE);
+
+ cdda_backend->num_open_files++;
+
+ g_vfs_job_open_for_read_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_read_set_handle (job, GINT_TO_POINTER (read_handle));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* We have to pass in a callback to paranoia_read, even though we don't use it */
+static void
+paranoia_callback (long int inpos, paranoia_cb_mode_t function)
+{
+}
+
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ int bytes_read;
+ long skip_bytes;
+ char *readbuf;
+ long desired_sector;
+ int bytes_to_copy;
+ long cursor_in_stream;
+
+ //g_warning ("read (%"G_GSSIZE_FORMAT") (@ %ld)", bytes_requested, read_handle->cursor);
+
+ /* header */
+ if (read_handle->cursor < read_handle->header_size)
+ {
+ skip_bytes = read_handle->cursor;
+ bytes_read = read_handle->header_size - read_handle->cursor;
+ readbuf = read_handle->header + skip_bytes;
+ goto read_data_done;
+ }
+
+ /* EOF */
+ if (read_handle->cursor >= read_handle->size)
+ {
+ skip_bytes = 0;
+ bytes_read = 0;
+ readbuf = NULL;
+ goto read_data_done;
+ }
+
+ cursor_in_stream = read_handle->cursor - read_handle->header_size;
+
+ desired_sector = cursor_in_stream / CDIO_CD_FRAMESIZE_RAW + read_handle->first_sector;
+
+ if (desired_sector == read_handle->buf_at_sector_num)
+ {
+ /* got it cached */
+
+ /* skip some bytes */
+ skip_bytes = cursor_in_stream - (desired_sector - read_handle->first_sector) * CDIO_CD_FRAMESIZE_RAW;
+ readbuf = read_handle->buf_at_sector + skip_bytes;
+ bytes_read = CDIO_CD_FRAMESIZE_RAW - skip_bytes;
+
+ //g_warning ("read from cache for cursor @ %ld", read_handle->buf_at_sector_num);
+ }
+ else
+ {
+ /* first check that we're at the right sector */
+ if (desired_sector != read_handle->sector_cursor)
+ {
+ cdio_paranoia_seek (read_handle->paranoia, desired_sector, SEEK_SET);
+ read_handle->sector_cursor = desired_sector;
+ //g_warning ("seeking cursor to %ld", read_handle->sector_cursor);
+ }
+
+ /* skip some bytes */
+ skip_bytes = cursor_in_stream - (read_handle->sector_cursor - read_handle->first_sector) * CDIO_CD_FRAMESIZE_RAW;
+ //g_warning ("advanced cursor to %ld", read_handle->sector_cursor);
+
+ readbuf = (char *) cdio_paranoia_read (read_handle->paranoia, paranoia_callback);
+
+ if (readbuf == NULL)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ /* Translators: paranoia is the name of the cd audio reading library */
+ _("Error from 'paranoia' on drive %s"), cdda_backend->device_path);
+ return;
+ }
+
+ read_handle->buf_at_sector_num = read_handle->sector_cursor;
+ memcpy (read_handle->buf_at_sector, readbuf, CDIO_CD_FRAMESIZE_RAW);
+
+ read_handle->sector_cursor++;
+
+ readbuf += skip_bytes;
+ bytes_read = CDIO_CD_FRAMESIZE_RAW - skip_bytes;
+
+
+ }
+
+ read_data_done:
+
+ bytes_to_copy = bytes_read;
+ if (bytes_requested < bytes_read)
+ bytes_to_copy = bytes_requested;
+
+ read_handle->cursor += bytes_to_copy;
+ cursor_in_stream = read_handle->cursor - read_handle->header_size;
+
+
+ if (bytes_to_copy > 0 && readbuf != NULL)
+ memcpy (buffer, readbuf, bytes_to_copy);
+
+ g_vfs_job_read_set_size (job, bytes_to_copy);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ long new_offset;
+
+ //g_warning ("seek_on_read (%d, %d)", (int)offset, type);
+
+ switch (type)
+ {
+ default:
+ case G_SEEK_SET:
+ new_offset = offset;
+ break;
+ case G_SEEK_CUR:
+ new_offset = read_handle->cursor + offset;
+ break;
+ case G_SEEK_END:
+ new_offset = read_handle->size + offset;
+ break;
+ }
+
+ if (new_offset < 0 || new_offset >= read_handle->size)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Error seeking in stream on drive %s"), cdda_backend->device_path);
+ }
+ else
+ {
+ read_handle->cursor = new_offset;
+
+ g_vfs_job_seek_read_set_offset (job, offset);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+}
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+
+ //g_warning ("close ()");
+
+ free_read_handle (read_handle);
+
+ cdda_backend->num_open_files--;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+set_info_for_track (GVfsBackendCdda *cdda_backend, GFileInfo *info, int track_num)
+{
+ char *header;
+ long first;
+ long last;
+ long header_size;
+ long content_size;
+ GIcon *icon;
+ GVfsBackendCddaTrack *track;
+
+ first = cdio_cddap_track_firstsector (cdda_backend->drive, track_num);
+ last = cdio_cddap_track_lastsector (cdda_backend->drive, track_num);
+ content_size = (last - first + 1) * CDIO_CD_FRAMESIZE_RAW;
+
+ header = create_header (cdda_backend, &header_size, content_size);
+ g_free (header);
+
+ //g_warning ("size=%ld for track %d", size, track_num);
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+ g_file_info_set_content_type (info, "audio/x-wav");
+ g_file_info_set_size (info, header_size + content_size);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+
+ track = g_list_nth_data (cdda_backend->tracks, track_num - 1);
+ if (track) {
+ if (track->title)
+ g_file_info_set_attribute_string (info, "xattr::org.gnome.audio.title", track->title);
+ if (track->artist)
+ g_file_info_set_attribute_string (info, "xattr::org.gnome.audio.artist", track->artist);
+ g_file_info_set_attribute_uint64 (info, "xattr::org.gnome.audio.duration", track->duration);
+ }
+
+ icon = g_themed_icon_new ("audio-x-generic");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+
+}
+
+#define SET_INFO(attr, value) if (value) g_file_info_set_attribute_string (info, attr, value);
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+ int track_num;
+ GError *error;
+
+ //g_warning ("get_file_info (%s)", filename);
+
+ if (strcmp (filename, "/") == 0)
+ {
+ GIcon *icon;
+ g_file_info_set_display_name (info, _("Audio Disc")); /* TODO: fill in from metadata */
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
+ SET_INFO ("xattr::org.gnome.audio.title", cdda_backend->album_title);
+ SET_INFO ("xattr::org.gnome.audio.artist", cdda_backend->album_artist);
+ SET_INFO ("xattr::org.gnome.audio.genre", cdda_backend->genre);
+ g_file_info_set_size (info, 0);
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+ else
+ {
+ g_file_info_set_name (info, filename);
+ g_file_info_set_display_name (info, filename);
+
+ track_num = get_track_num_from_name (cdda_backend, filename);
+ if (track_num == -1)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
+
+ if (track_num > cdda_backend->drive->tracks)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File doesn't exist"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
+
+ if (! cdio_cddap_track_audiop (cdda_backend->drive, track_num))
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("The file does not exist or isn't an audio track"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
+
+ set_info_for_track (cdda_backend, info, track_num);
+ }
+
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+ GFileInfo *info;
+ GList *l;
+ int n;
+
+ //g_warning ("enumerate (%s)", filename);
+
+ l = NULL;
+ for (n = 1; n <= cdda_backend->drive->tracks; n++)
+ {
+ char *name;
+
+ /* not audio track */
+ if (! cdio_cddap_track_audiop (cdda_backend->drive, n))
+ continue;
+
+ info = g_file_info_new ();
+
+ name = g_strdup_printf ("Track %d.wav", n);
+ g_file_info_set_name (info, name);
+ g_file_info_set_display_name (info, name);
+ g_free (name);
+
+ set_info_for_track (cdda_backend, info, n);
+
+ l = g_list_append (l, info);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_vfs_job_enumerate_add_infos (job, l);
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+
+ g_vfs_job_enumerate_done (job);
+}
+
+static void
+do_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GVfsBackendCdda *cdda_backend = G_VFS_BACKEND_CDDA (backend);
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "cdda");
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
+
+ if (cdda_backend->size > 0)
+ {
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,
+ cdda_backend->size);
+ }
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
+ 0);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+
+static void
+g_vfs_backend_cdda_class_init (GVfsBackendCddaClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_cdda_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->mount = do_mount;
+ backend_class->unmount = do_unmount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->read = do_read;
+ backend_class->seek_on_read = do_seek_on_read;
+ backend_class->close_read = do_close_read;
+ backend_class->query_info = do_query_info;
+ backend_class->query_fs_info = do_query_fs_info;
+ backend_class->enumerate = do_enumerate;
+}
+
+void
+g_vfs_cdda_daemon_init (void)
+{
+ g_set_application_name (_("Audio CD Filesystem Service"));
+}
diff --git a/trunk/daemon/gvfsbackendcdda.h b/trunk/daemon/gvfsbackendcdda.h
new file mode 100644
index 00000000..4abba370
--- /dev/null
+++ b/trunk/daemon/gvfsbackendcdda.h
@@ -0,0 +1,54 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_CDDA_H__
+#define __G_VFS_BACKEND_CDDA_H__
+
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_CDDA (g_vfs_backend_cdda_get_type ())
+#define G_VFS_BACKEND_CDDA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_CDDA, GVfsBackendCdda))
+#define G_VFS_BACKEND_CDDA_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_CDDA, GVfsBackendCddaClass))
+#define G_VFS_IS_BACKEND_CDDA(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_CDDA))
+#define G_VFS_IS_BACKEND_CDDA_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_CDDA))
+#define G_VFS_BACKEND_CDDA_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_CDDA, GVfsBackendCddaClass))
+
+typedef struct _GVfsBackendCdda GVfsBackendCdda;
+typedef struct _GVfsBackendCddaClass GVfsBackendCddaClass;
+
+struct _GVfsBackendCddaClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_cdda_get_type (void) G_GNUC_CONST;
+
+GVfsBackendCdda *g_vfs_backend_cdda_new (void);
+
+#define BACKEND_SETUP_FUNC g_vfs_cdda_daemon_init
+void g_vfs_cdda_daemon_init (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_CDDA_H__ */
diff --git a/trunk/daemon/gvfsbackendcomputer.c b/trunk/daemon/gvfsbackendcomputer.c
new file mode 100644
index 00000000..aaec50b5
--- /dev/null
+++ b/trunk/daemon/gvfsbackendcomputer.c
@@ -0,0 +1,1125 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Alexander Larsson <alexl@redhat.com>
+ * Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+#include "gvfsbackendcomputer.h"
+#include "gvfsmonitor.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobmountmountable.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobdelete.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsdaemonprotocol.h"
+
+typedef struct {
+ char *filename;
+ char *display_name;
+ GIcon *icon;
+ GFile *root;
+ int prio;
+ gboolean can_mount;
+ gboolean can_unmount;
+ gboolean can_eject;
+
+ GDrive *drive;
+ GVolume *volume;
+ GMount *mount;
+} ComputerFile;
+
+static ComputerFile root = { "/" };
+
+struct _GVfsBackendComputer
+{
+ GVfsBackend parent_instance;
+
+ GVolumeMonitor *volume_monitor;
+
+ GVfsMonitor *root_monitor;
+
+ GList *files;
+
+ guint recompute_idle_tag;
+
+ GMountSpec *mount_spec;
+};
+
+G_DEFINE_TYPE (GVfsBackendComputer, g_vfs_backend_computer, G_VFS_TYPE_BACKEND)
+
+static void
+computer_file_free (ComputerFile *file)
+{
+ g_free (file->filename);
+ g_free (file->display_name);
+ if (file->icon)
+ g_object_unref (file->icon);
+ if (file->root)
+ g_object_unref (file->root);
+
+ if (file->drive)
+ g_object_unref (file->drive);
+ if (file->volume)
+ g_object_unref (file->volume);
+ if (file->mount)
+ g_object_unref (file->mount);
+
+ g_slice_free (ComputerFile, file);
+}
+
+/* Assumes filename equal */
+static gboolean
+computer_file_equal (ComputerFile *a,
+ ComputerFile *b)
+{
+ if (strcmp (a->display_name, b->display_name) != 0)
+ return FALSE;
+
+ if (!g_icon_equal (a->icon, b->icon))
+ return FALSE;
+
+ if ((a->root != NULL && b->root != NULL &&
+ !g_file_equal (a->root, b->root)) ||
+ (a->root != NULL && b->root == NULL) ||
+ (a->root == NULL && b->root != NULL))
+ return FALSE;
+
+ if (a->prio != b->prio)
+ return FALSE;
+
+ if (a->can_mount != b->can_mount ||
+ a->can_unmount != b->can_unmount ||
+ a->can_eject != b->can_eject)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void object_changed (GVolumeMonitor *monitor,
+ gpointer object,
+ GVfsBackendComputer *backend);
+
+static void
+g_vfs_backend_computer_finalize (GObject *object)
+{
+ GVfsBackendComputer *backend;
+
+ backend = G_VFS_BACKEND_COMPUTER (object);
+
+ if (backend->volume_monitor)
+ {
+ g_signal_handlers_disconnect_by_func(backend->volume_monitor, object_changed, backend);
+ g_object_unref (backend->volume_monitor);
+ }
+
+ g_mount_spec_unref (backend->mount_spec);
+
+ if (backend->recompute_idle_tag)
+ {
+ g_source_remove (backend->recompute_idle_tag);
+ backend->recompute_idle_tag = 0;
+ }
+
+ g_object_unref (backend->root_monitor);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_computer_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_computer_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_computer_init (GVfsBackendComputer *computer_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (computer_backend);
+ GMountSpec *mount_spec;
+
+ g_vfs_backend_set_display_name (backend, _("Computer"));
+ g_vfs_backend_set_icon_name (backend, "computer");
+ g_vfs_backend_set_user_visible (backend, FALSE);
+
+ mount_spec = g_mount_spec_new ("computer");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ computer_backend->mount_spec = mount_spec;
+}
+
+static gboolean
+filename_is_used (GList *files, const char *filename)
+{
+ ComputerFile *file;
+
+ while (files != NULL)
+ {
+ file = files->data;
+
+ if (file->filename == NULL)
+ return FALSE;
+
+ if (strcmp (file->filename, filename) == 0)
+ return TRUE;
+
+ files = files->next;
+ }
+ return FALSE;
+}
+
+static int
+sort_file_by_filename (ComputerFile *a, ComputerFile *b)
+{
+ return strcmp (a->filename, b->filename);
+}
+
+static void
+convert_slashes (char *str)
+{
+ char *s;
+
+ while ((s = strchr (str, '/')) != NULL)
+ *s = '\\';
+}
+
+static void
+update_from_files (GVfsBackendComputer *backend,
+ GList *files)
+{
+ GList *old_files;
+ GList *oldl, *newl;
+ char *filename;
+ ComputerFile *old, *new;
+ int cmp;
+
+ old_files = backend->files;
+ backend->files = files;
+
+ /* Generate change events */
+ oldl = old_files;
+ newl = files;
+ while (oldl != NULL || newl != NULL)
+ {
+ if (oldl == NULL)
+ {
+ cmp = 1;
+ new = newl->data;
+ old = NULL;
+ }
+ else if (newl == NULL)
+ {
+ cmp = -1;
+ new = NULL;
+ old = oldl->data;
+ }
+ else
+ {
+ new = newl->data;
+ old = oldl->data;
+ cmp = strcmp (old->filename, new->filename);
+ }
+
+ if (cmp == 0)
+ {
+ if (!computer_file_equal (old, new))
+ {
+ filename = g_strconcat ("/", new->filename, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_CHANGED,
+ filename,
+ NULL);
+ g_free (filename);
+ }
+
+ oldl = oldl->next;
+ newl = newl->next;
+ }
+ else if (cmp < 0)
+ {
+ filename = g_strconcat ("/", old->filename, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_DELETED,
+ filename,
+ NULL);
+ g_free (filename);
+ oldl = oldl->next;
+ }
+ else
+ {
+ filename = g_strconcat ("/", new->filename, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_CREATED,
+ filename,
+ NULL);
+ g_free (filename);
+ newl = newl->next;
+ }
+ }
+
+ g_list_foreach (old_files, (GFunc)computer_file_free, NULL);
+}
+
+static void
+recompute_files (GVfsBackendComputer *backend)
+{
+ GVolumeMonitor *volume_monitor;
+ GList *drives, *volumes, *mounts, *l, *ll;
+ GDrive *drive;
+ GVolume *volume;
+ GMount *mount;
+ ComputerFile *file;
+ GList *files;
+ char *basename, *filename;
+ const char *extension;
+ int uniq;
+
+ volume_monitor = backend->volume_monitor;
+
+ files = NULL;
+
+ /* first go through all connected drives */
+ drives = g_volume_monitor_get_connected_drives (volume_monitor);
+ for (l = drives; l != NULL; l = l->next)
+ {
+ drive = l->data;
+
+ volumes = g_drive_get_volumes (drive);
+ if (volumes != NULL)
+ {
+ for (ll = volumes; ll != NULL; ll = ll->next)
+ {
+ volume = ll->data;
+
+ file = g_slice_new0 (ComputerFile);
+ file->drive = g_object_ref (drive);
+ file->volume = volume; /* Takes ref */
+ file->mount = g_volume_get_mount (volume);
+ file->prio = -3;
+ files = g_list_prepend (files, file);
+ }
+ }
+ else
+ {
+ /* No volume, single drive */
+
+ file = g_slice_new0 (ComputerFile);
+ file->drive = g_object_ref (drive);
+ file->volume = NULL;
+ file->mount = NULL;
+ file->prio = -3;
+
+ files = g_list_prepend (files, file);
+ }
+
+ g_object_unref (drive);
+ }
+ g_list_free (drives);
+
+ /* add all volumes that is not associated with a drive */
+ volumes = g_volume_monitor_get_volumes (volume_monitor);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ volume = l->data;
+ drive = g_volume_get_drive (volume);
+ if (drive == NULL)
+ {
+ file = g_slice_new0 (ComputerFile);
+ file->drive = NULL;
+ file->volume = g_object_ref (volume);
+ file->mount = g_volume_get_mount (volume);
+ file->prio = -2;
+
+ files = g_list_prepend (files, file);
+ }
+ else
+ g_object_unref (drive);
+
+ g_object_unref (volume);
+ }
+ g_list_free (volumes);
+
+ /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ mount = l->data;
+ volume = g_mount_get_volume (mount);
+ if (volume == NULL && !g_mount_is_shadowed (mount))
+ {
+ file = g_slice_new0 (ComputerFile);
+ file->drive = NULL;
+ file->volume = NULL;
+ file->mount = g_object_ref (mount);
+ file->prio = -1;
+
+ files = g_list_prepend (files, file);
+ }
+ else
+ g_object_unref (volume);
+
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+
+ files = g_list_reverse (files);
+
+ for (l = files; l != NULL; l = l->next)
+ {
+ file = l->data;
+
+ if (file->mount)
+ {
+ file->icon = g_mount_get_icon (file->mount);
+ file->display_name = g_mount_get_name (file->mount);
+ file->root = g_mount_get_root (file->mount);
+ file->can_unmount = g_mount_can_unmount (file->mount);
+ file->can_eject = g_mount_can_eject (file->mount);
+ }
+ else if (file->volume)
+ {
+ file->icon = g_volume_get_icon (file->volume);
+ file->display_name = g_volume_get_name (file->volume);
+ file->can_mount = g_volume_can_mount (file->volume);
+ file->root = NULL;
+ file->can_eject = g_volume_can_eject (file->volume);
+ }
+ else /* drive */
+ {
+ file->icon = g_drive_get_icon (file->drive);
+ file->display_name = g_drive_get_name (file->drive);
+ file->can_eject = g_drive_can_eject (file->drive);
+ file->can_mount = TRUE;
+ }
+
+ if (file->drive)
+ {
+ basename = g_drive_get_name (file->drive);
+ extension = ".drive";
+ }
+ else if (file->volume)
+ {
+ basename = g_volume_get_name (file->volume);
+ extension = ".volume";
+ }
+ else /* mount */
+ {
+ basename = g_mount_get_name (file->mount);
+ extension = ".mount";
+ }
+
+ convert_slashes (basename); /* No slashes in filenames */
+ uniq = 1;
+ filename = g_strconcat (basename, extension, NULL);
+ while (filename_is_used (files, filename))
+ {
+ g_free (filename);
+ filename = g_strdup_printf ("%s-%d%s",
+ basename,
+ uniq++,
+ extension);
+ }
+
+ g_free (basename);
+ file->filename = filename;
+ }
+
+ file = g_slice_new0 (ComputerFile);
+ file->filename = g_strdup ("root.link");
+ file->display_name = g_strdup (_("Filesystem"));
+ file->icon = g_themed_icon_new ("drive-harddisk");
+ file->root = g_file_new_for_path ("/");
+ file->prio = 0;
+
+ files = g_list_prepend (files, file);
+
+ files = g_list_sort (files, (GCompareFunc)sort_file_by_filename);
+
+ update_from_files (backend, files);
+}
+
+static gboolean
+recompute_files_in_idle (GVfsBackendComputer *backend)
+{
+ backend->recompute_idle_tag = 0;
+
+ recompute_files (backend);
+
+ return FALSE;
+}
+
+static void
+object_changed (GVolumeMonitor *monitor,
+ gpointer object,
+ GVfsBackendComputer *backend)
+{
+ if (backend->recompute_idle_tag == 0)
+ backend->recompute_idle_tag =
+ g_idle_add ((GSourceFunc)recompute_files_in_idle,
+ backend);
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendComputer *computer_backend = G_VFS_BACKEND_COMPUTER (backend);
+ int i;
+ char *signals[] = {
+ "volume-added",
+ "volume-removed",
+ "volume-changed",
+ "mount-added",
+ "mount-removed",
+ "mount-changed",
+ "drive-connected",
+ "drive-disconnected",
+ "drive-changed",
+ NULL
+ };
+
+ computer_backend->volume_monitor = g_volume_monitor_get ();
+
+ /* TODO: connect all signals to object_changed */
+
+ for (i = 0; signals[i] != NULL; i++)
+ g_signal_connect_data (computer_backend->volume_monitor,
+ signals[i],
+ (GCallback)object_changed,
+ backend,
+ NULL, 0);
+
+ computer_backend->root_monitor = g_vfs_monitor_new (backend);
+
+ recompute_files (computer_backend);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static ComputerFile *
+lookup (GVfsBackendComputer *backend,
+ GVfsJob *job,
+ const char *filename)
+{
+ GList *l;
+ ComputerFile *file;
+
+ if (*filename != '/')
+ goto out;
+
+ while (*filename == '/')
+ filename++;
+
+ if (*filename == 0)
+ return &root;
+
+ if (strchr (filename, '/') != NULL)
+ goto out;
+
+ for (l = backend->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+
+ if (strcmp (file->filename, filename) == 0)
+ return file;
+ }
+
+ out:
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ return NULL;
+}
+
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ ComputerFile *file;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file == &root)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+ else if (file != NULL)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't open mountable file"));
+ return TRUE;
+}
+
+static void
+file_info_from_file (ComputerFile *file,
+ GFileInfo *info)
+{
+ char *uri;
+
+ g_file_info_set_name (info, file->filename);
+ g_file_info_set_display_name (info, file->display_name);
+
+ if (file->icon)
+ g_file_info_set_icon (info, file->icon);
+
+ if (file->root)
+ {
+ uri = g_file_get_uri (file->root);
+
+ g_file_info_set_attribute_string (info,
+ G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ uri);
+ g_free (uri);
+ }
+
+ g_file_info_set_sort_order (info, file->prio);
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, file->can_mount);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, file->can_unmount);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT, file->can_eject);
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ ComputerFile *file;
+ GList *l;
+ GFileInfo *info;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file != &root)
+ {
+ if (file != NULL)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ return TRUE;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ /* Enumerate root */
+ for (l = G_VFS_BACKEND_COMPUTER (backend)->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+
+ info = g_file_info_new ();
+
+ file_info_from_file (file, info);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ g_vfs_job_enumerate_done (job);
+
+ return TRUE;
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ ComputerFile *file;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file == &root)
+ {
+ GIcon *icon;
+
+ g_file_info_set_name (info, "/");
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_display_name (info, _("Computer"));
+ icon = g_themed_icon_new ("computer");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_content_type (info, "inode/directory");
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else if (file != NULL)
+ {
+ file_info_from_file (file, info);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+static gboolean
+try_create_dir_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ ComputerFile *file;
+ GVfsBackendComputer *computer_backend;
+
+ computer_backend = G_VFS_BACKEND_COMPUTER (backend);
+
+ file = lookup (computer_backend,
+ G_VFS_JOB (job), filename);
+
+ if (file != &root)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+
+ return TRUE;
+ }
+
+ g_vfs_job_create_monitor_set_monitor (job,
+ computer_backend->root_monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static void
+mount_volume_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobMountMountable *job = user_data;
+ GError *error;
+ GMount *mount;
+ GVolume *volume;
+ GFile *root;
+ char *uri;
+
+ volume = G_VOLUME (source_object);
+
+ /* TODO: We're leaking the GMountOperation here */
+
+ error = NULL;
+ if (g_volume_mount_finish (volume, res, &error))
+ {
+ mount = g_volume_get_mount (volume);
+
+ if (mount)
+ {
+ root = g_mount_get_root (mount);
+ uri = g_file_get_uri (root);
+ g_vfs_job_mount_mountable_set_target_uri (job,
+ uri,
+ FALSE);
+ g_free (uri);
+ g_object_unref (root);
+ g_object_unref (mount);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Internal error: %s"), "No mount object for mounted volume");
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+mount_volume_from_drive (GDrive *drive,
+ GVfsJob *job,
+ GMountOperation *mount_op)
+{
+ GList *volumes;
+ GVolume *volume;
+
+ volumes = g_drive_get_volumes (drive);
+ if (volumes)
+ {
+ volume = G_VOLUME (volumes->data);
+ g_volume_mount (volume,
+ 0,
+ mount_op,
+ G_VFS_JOB (job)->cancellable,
+ mount_volume_cb,
+ job);
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't mount file"));
+ }
+
+ g_list_foreach (volumes, (GFunc)g_object_unref, NULL);
+ g_list_free (volumes);
+}
+
+static void
+report_no_media_error (GVfsJob *job)
+{
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("No media in the drive"));
+}
+
+typedef struct {
+ GVfsJobMountMountable *job;
+ GMountOperation *mount_op;
+} PollForMediaData;
+
+static void
+poll_for_media_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PollForMediaData *data = user_data;
+ GDrive *drive;
+ GError *error;
+
+ drive = G_DRIVE (source_object);
+ error = NULL;
+
+ if (g_drive_poll_for_media_finish (drive, res, &error))
+ {
+ gboolean has_media;
+ has_media = g_drive_has_media (drive);
+
+ if (!has_media)
+ {
+ report_no_media_error (G_VFS_JOB (data->job));
+ }
+ else
+ {
+ mount_volume_from_drive (drive, G_VFS_JOB (data->job), data->mount_op);
+ g_slice_free (PollForMediaData, data);
+ }
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (data->job), error);
+ g_error_free (error);
+ }
+}
+
+static gboolean
+try_mount_mountable (GVfsBackend *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source)
+{
+ ComputerFile *file;
+ GMountOperation *mount_op;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file == &root)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ _("Not a mountable file"));
+ else if (file != NULL)
+ {
+ if (file->volume)
+ {
+ mount_op = g_mount_source_get_operation (mount_source);
+ g_volume_mount (file->volume,
+ 0,
+ mount_op,
+ G_VFS_JOB (job)->cancellable,
+ mount_volume_cb,
+ job);
+ }
+
+ else if (file->drive)
+ {
+ if (!g_drive_has_media (file->drive))
+ {
+ if (!g_drive_can_poll_for_media (file->drive))
+ report_no_media_error (G_VFS_JOB (job));
+ else
+ {
+ PollForMediaData *data;
+
+ data = g_slice_new0 (PollForMediaData);
+ mount_op = g_mount_source_get_operation (mount_source);
+ data->job = job;
+ data->mount_op = mount_op;
+ if (!g_drive_is_media_check_automatic (file->drive))
+ g_drive_poll_for_media (file->drive,
+ G_VFS_JOB (job)->cancellable,
+ poll_for_media_cb,
+ data);
+ else
+ report_no_media_error (G_VFS_JOB (job));
+ }
+ }
+ else
+ {
+ mount_op = g_mount_source_get_operation (mount_source);
+ mount_volume_from_drive (file->drive, G_VFS_JOB (job), mount_op);
+ }
+ }
+
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't mount file"));
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+unmount_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobMountMountable *job = user_data;
+ GError *error;
+ GMount *mount;
+
+ mount = G_MOUNT (source_object);
+
+ error = NULL;
+ if (g_mount_unmount_finish (mount, res, &error))
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+
+static gboolean
+try_unmount_mountable (GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags)
+{
+ ComputerFile *file;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file == &root)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ _("Not a mountable file"));
+ else if (file != NULL)
+ {
+ if (file->mount)
+ {
+ g_mount_unmount (file->mount,
+ flags,
+ G_VFS_JOB (job)->cancellable,
+ unmount_mount_cb,
+ job);
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't unmount file"));
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+eject_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobMountMountable *job = user_data;
+ GError *error;
+ GMount *mount;
+
+ mount = G_MOUNT (source_object);
+
+ error = NULL;
+ if (g_mount_eject_finish (mount, res, &error))
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+eject_volume_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobMountMountable *job = user_data;
+ GError *error;
+ GVolume *volume;
+
+ volume = G_VOLUME (source_object);
+
+ error = NULL;
+ if (g_volume_eject_finish (volume, res, &error))
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+
+static void
+eject_drive_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobMountMountable *job = user_data;
+ GError *error;
+ GDrive *drive;
+
+ drive = G_DRIVE (source_object);
+
+ error = NULL;
+ if (g_drive_eject_finish (drive, res, &error))
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static gboolean
+try_eject_mountable (GVfsBackend *backend,
+ GVfsJobUnmountMountable *job,
+ const char *filename,
+ GMountUnmountFlags flags)
+{
+ ComputerFile *file;
+
+ file = lookup (G_VFS_BACKEND_COMPUTER (backend),
+ G_VFS_JOB (job), filename);
+
+ if (file == &root)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ _("Not a mountable file"));
+ else if (file != NULL)
+ {
+ if (file->mount)
+ {
+ g_mount_eject (file->mount,
+ flags,
+ G_VFS_JOB (job)->cancellable,
+ eject_mount_cb,
+ job);
+ }
+ else if (file->volume)
+ {
+ g_volume_eject (file->volume,
+ flags,
+ G_VFS_JOB (job)->cancellable,
+ eject_volume_cb,
+ job);
+ }
+ else if (file->drive)
+ {
+ g_drive_eject (file->drive,
+ flags,
+ G_VFS_JOB (job)->cancellable,
+ eject_drive_cb,
+ job);
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't eject file"));
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_computer_class_init (GVfsBackendComputerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_computer_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_create_dir_monitor = try_create_dir_monitor;
+ backend_class->try_mount_mountable = try_mount_mountable;
+ backend_class->try_unmount_mountable = try_unmount_mountable;
+ backend_class->try_eject_mountable = try_eject_mountable;
+}
diff --git a/trunk/daemon/gvfsbackendcomputer.h b/trunk/daemon/gvfsbackendcomputer.h
new file mode 100644
index 00000000..03d781df
--- /dev/null
+++ b/trunk/daemon/gvfsbackendcomputer.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_COMPUTER_H__
+#define __G_VFS_BACKEND_COMPUTER_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_COMPUTER (g_vfs_backend_computer_get_type ())
+#define G_VFS_BACKEND_COMPUTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputer))
+#define G_VFS_BACKEND_COMPUTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputerClass))
+#define G_VFS_IS_BACKEND_COMPUTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_COMPUTER))
+#define G_VFS_IS_BACKEND_COMPUTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_COMPUTER))
+#define G_VFS_BACKEND_COMPUTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_COMPUTER, GVfsBackendComputerClass))
+
+typedef struct _GVfsBackendComputer GVfsBackendComputer;
+typedef struct _GVfsBackendComputerClass GVfsBackendComputerClass;
+
+struct _GVfsBackendComputerClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_computer_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_COMPUTER_H__ */
diff --git a/trunk/daemon/gvfsbackenddav.c b/trunk/daemon/gvfsbackenddav.c
new file mode 100644
index 00000000..aee90348
--- /dev/null
+++ b/trunk/daemon/gvfsbackenddav.c
@@ -0,0 +1,2335 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <libsoup/soup.h>
+
+/* LibXML2 includes */
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include "gvfsbackenddav.h"
+#include "gvfskeyring.h"
+
+#include "gvfsjobmount.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+
+#include "soup-input-stream.h"
+#include "soup-output-stream.h"
+
+#ifdef HAVE_AVAHI
+#include "gvfsdnssdutils.h"
+#include "gvfsdnssdresolver.h"
+#endif
+
+typedef struct _MountAuthData MountAuthData;
+
+static void mount_auth_info_free (MountAuthData *info);
+
+
+#ifdef HAVE_AVAHI
+static void dns_sd_resolver_changed (GVfsDnsSdResolver *resolver, GVfsBackendDav *dav_backend);
+#endif
+
+typedef struct _AuthInfo {
+
+ /* for server authentication */
+ char *username;
+ char *password;
+ char *realm;
+
+ GPasswordSave pw_save;
+
+} AuthInfo;
+
+struct _MountAuthData {
+
+ SoupSession *session;
+ GMountSource *mount_source;
+
+ AuthInfo server_auth;
+ AuthInfo proxy_auth;
+
+};
+
+struct _GVfsBackendDav
+{
+ GVfsBackendHttp parent_instance;
+
+ MountAuthData auth_info;
+
+#ifdef HAVE_AVAHI
+ /* only set if we're handling a [dav|davs]+sd:// mounts */
+ GVfsDnsSdResolver *resolver;
+#endif
+};
+
+G_DEFINE_TYPE (GVfsBackendDav, g_vfs_backend_dav, G_VFS_TYPE_BACKEND_HTTP);
+
+static void
+g_vfs_backend_dav_finalize (GObject *object)
+{
+ GVfsBackendDav *dav_backend;
+
+ dav_backend = G_VFS_BACKEND_DAV (object);
+
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (dav_backend->resolver, dns_sd_resolver_changed, dav_backend);
+ g_object_unref (dav_backend->resolver);
+ }
+#endif
+
+ mount_auth_info_free (&(dav_backend->auth_info));
+
+ if (G_OBJECT_CLASS (g_vfs_backend_dav_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_dav_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_dav_init (GVfsBackendDav *backend)
+{
+ g_vfs_backend_set_user_visible (G_VFS_BACKEND (backend), TRUE);
+}
+
+/* ************************************************************************* */
+/* Small utility functions */
+
+static inline gboolean
+sm_has_header (SoupMessage *msg, const char *header)
+{
+ return soup_message_headers_get (msg->response_headers, header) != NULL;
+}
+
+static char *
+path_get_parent_dir (const char *path)
+{
+ char *parent;
+ size_t len;
+
+ len = strlen (path);
+
+ while (len > 0 && path[len - 1] == '/')
+ len--;
+
+ if (len == 0)
+ return NULL;
+
+ parent = g_strrstr_len (path, len, "/");
+
+ if (parent == NULL)
+ return NULL;
+
+ return g_strndup (path, (parent - path) + 1);
+}
+
+/* message utility functions */
+
+static void
+message_add_destination_header (SoupMessage *msg,
+ SoupURI *uri)
+{
+ char *string;
+
+ string = soup_uri_to_string (uri, FALSE);
+ soup_message_headers_append (msg->request_headers,
+ "Destination",
+ string);
+ g_free (string);
+}
+static void
+message_add_overwrite_header (SoupMessage *msg,
+ gboolean overwrite)
+{
+ soup_message_headers_append (msg->request_headers,
+ "Overwrite",
+ overwrite ? "T" : "F");
+}
+
+static void
+message_add_redirect_header (SoupMessage *msg,
+ GFileQueryInfoFlags flags)
+{
+ const char *header_redirect;
+
+ /* RFC 4437 */
+ if (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
+ header_redirect = "F";
+ else
+ header_redirect = "T";
+
+ soup_message_headers_append (msg->request_headers,
+ "Apply-To-Redirect-Ref",
+ header_redirect);
+}
+
+static inline gboolean
+str_equal (const char *a, const char *b, gboolean insensitive)
+{
+ if (a == NULL || b == NULL)
+ return a == b;
+
+ return insensitive ? !g_ascii_strcasecmp (a, b) : !strcmp (a, b);
+}
+
+static gboolean
+path_equal (const char *a, const char *b, gboolean relax)
+{
+ gboolean res;
+ size_t a_len, b_len;
+
+ if (relax == FALSE)
+ return str_equal (a, b, FALSE);
+
+ if (a == NULL || b == NULL)
+ return a == b;
+
+ a_len = strlen (a);
+ b_len = strlen (b);
+
+ while (a_len > 0 && a[a_len - 1] == '/')
+ a_len--;
+
+ while (b_len > 0 && b[b_len - 1] == '/')
+ b_len--;
+
+ if (a_len == b_len)
+ res = ! strncmp (a, b, a_len);
+ else
+ res = FALSE;
+
+ return res;
+}
+
+/* Like soup_uri_equal */
+static gboolean
+dav_uri_match (SoupURI *a, SoupURI *b, gboolean relax)
+{
+ if (a->scheme != b->scheme ||
+ a->port != b->port ||
+ ! str_equal (a->user, b->user, FALSE) ||
+ ! str_equal (a->password, b->password, FALSE) ||
+ ! str_equal (a->host, b->host, TRUE) ||
+ ! path_equal (a->path, b->path, relax) ||
+ ! str_equal (a->query, b->query, FALSE) ||
+ ! str_equal (a->fragment, b->fragment, FALSE))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+message_should_apply_redir_ref (SoupMessage *msg)
+{
+ const char *header;
+
+ header = soup_message_headers_get (msg->request_headers,
+ "Apply-To-Redirect-Ref");
+
+ if (header == NULL || g_ascii_strcasecmp (header, "T"))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* redirection */
+static void
+redirect_handler (SoupMessage *msg, gpointer user_data)
+{
+ SoupSession *session = user_data;
+ const char *new_loc;
+ SoupURI *new_uri;
+ SoupURI *old_uri;
+ guint status;
+ gboolean redirect;
+
+ status = msg->status_code;
+ new_loc = soup_message_headers_get (msg->response_headers, "Location");
+
+ /* If we don't have a location to redirect to, just fail */
+ if (new_loc == NULL)
+ return;
+
+ if (!SOUP_STATUS_IS_REDIRECTION(status))
+ return;
+
+ new_uri = soup_uri_new_with_base (soup_message_get_uri (msg), new_loc);
+ if (new_uri == NULL)
+ {
+ soup_message_set_status_full (msg,
+ SOUP_STATUS_MALFORMED,
+ "Invalid Redirect URL");
+ return;
+ }
+
+ old_uri = soup_message_get_uri (msg);
+
+ /* copy over username and password to new_uri */
+ soup_uri_set_user(new_uri, old_uri->user);
+ soup_uri_set_password(new_uri, old_uri->password);
+
+ /* Check if this is a trailing slash redirect (i.e. /a/b to /a/b/),
+ * redirect it right away
+ */
+ redirect = dav_uri_match (new_uri, old_uri, TRUE);
+
+ if (redirect == TRUE)
+ {
+ const char *dest;
+
+ dest = soup_message_headers_get (msg->request_headers,
+ "Destination");
+
+ if (dest && g_str_has_suffix (dest, "/") == FALSE)
+ {
+ char *new_dest = g_strconcat (dest, "/", NULL);
+ soup_message_headers_replace (msg->request_headers,
+ "Destination",
+ new_dest);
+ g_free (new_dest);
+ }
+ }
+ else if (message_should_apply_redir_ref (msg))
+ {
+
+
+ if (status == SOUP_STATUS_MOVED_PERMANENTLY ||
+ status == SOUP_STATUS_TEMPORARY_REDIRECT)
+ {
+
+ /* Only corss-site redirect safe methods */
+ if (msg->method == SOUP_METHOD_GET &&
+ msg->method == SOUP_METHOD_HEAD &&
+ msg->method == SOUP_METHOD_OPTIONS &&
+ msg->method == SOUP_METHOD_PROPFIND)
+ redirect = TRUE;
+ }
+
+#if 0
+ else if (msg->status_code == SOUP_STATUS_SEE_OTHER ||
+ msg->status_code == SOUP_STATUS_FOUND)
+ {
+ /* Redirect using a GET */
+ g_object_set (msg,
+ SOUP_MESSAGE_METHOD, SOUP_METHOD_GET,
+ NULL);
+ soup_message_set_request (msg, NULL,
+ SOUP_MEMORY_STATIC, NULL, 0);
+ soup_message_headers_set_encoding (msg->request_headers,
+ SOUP_ENCODING_NONE);
+ }
+#endif
+ /* ELSE:
+ *
+ * Two possibilities:
+ *
+ * 1) It's a non-redirecty 3xx response (300, 304,
+ * 305, 306)
+ * 2) It's some newly-defined 3xx response (308+)
+ *
+ * We ignore both of these cases. In the first,
+ * redirecting would be explicitly wrong, and in the
+ * last case, we have no clue if the 3xx response is
+ * supposed to be redirecty or non-redirecty. Plus,
+ * 2616 says unrecognized status codes should be
+ * treated as the equivalent to the x00 code, and we
+ * don't redirect on 300, so therefore we shouldn't
+ * redirect on 308+ either.
+ */
+ }
+
+ if (redirect)
+ {
+ soup_message_set_uri (msg, new_uri);
+ soup_session_requeue_message (session, msg);
+ }
+
+ soup_uri_free (new_uri);
+}
+
+static guint
+g_vfs_backend_dav_send_message (GVfsBackend *backend, SoupMessage *message)
+{
+ GVfsBackendHttp *http_backend;
+ SoupSession *session;
+
+ http_backend = G_VFS_BACKEND_HTTP (backend);
+ session = http_backend->session;
+
+ /* We have our own custom redirect handler */
+ soup_message_set_flags (message, SOUP_MESSAGE_NO_REDIRECT);
+
+ soup_message_add_header_handler (message, "got_body", "Location",
+ G_CALLBACK (redirect_handler), session);
+
+ return http_backend_send_message (backend, message);
+}
+
+/* ************************************************************************* */
+/* generic xml parsing functions */
+
+static inline gboolean
+node_has_name (xmlNodePtr node, const char *name)
+{
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ return ! strcmp ((char *) node->name, name);
+}
+
+static inline gboolean
+node_has_name_ns (xmlNodePtr node, const char *name, const char *ns_href)
+{
+ gboolean has_name;
+ gboolean has_ns;
+
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ has_name = has_ns = TRUE;
+
+ if (name)
+ has_name = node->name && ! strcmp ((char *) node->name, name);
+
+ if (ns_href)
+ has_ns = node->ns && node->ns->href &&
+ ! g_ascii_strcasecmp ((char *) node->ns->href, ns_href);
+
+ return has_name && has_ns;
+}
+
+static inline gboolean
+node_is_element (xmlNodePtr node)
+{
+ return node->type == XML_ELEMENT_NODE && node->name != NULL;
+}
+
+
+static inline gboolean
+node_is_element_with_name (xmlNodePtr node, const char *name)
+{
+ return node->type == XML_ELEMENT_NODE &&
+ node->name != NULL &&
+ ! strcmp ((char *) node->name, name);
+}
+
+static const char *
+node_get_content (xmlNodePtr node)
+{
+ if (node == NULL)
+ return NULL;
+
+ switch (node->type)
+ {
+ case XML_ELEMENT_NODE:
+ return node_get_content (node->children);
+ break;
+ case XML_TEXT_NODE:
+ return (const char *) node->content;
+ break;
+ default:
+ return NULL;
+ }
+}
+
+typedef struct _xmlNodeIter {
+
+ xmlNodePtr cur_node;
+ xmlNodePtr next_node;
+
+ const char *name;
+ const char *ns_href;
+
+ void *user_data;
+
+} xmlNodeIter;
+
+static xmlNodePtr
+xml_node_iter_next (xmlNodeIter *iter)
+{
+ xmlNodePtr node;
+
+ while ((node = iter->next_node))
+ {
+ iter->next_node = node->next;
+
+ if (node->type == XML_ELEMENT_NODE) {
+ if (node_has_name_ns (node, iter->name, iter->ns_href))
+ break;
+ }
+ }
+
+ iter->cur_node = node;
+ return node;
+}
+
+static void *
+xml_node_iter_get_user_data (xmlNodeIter *iter)
+{
+ return iter->user_data;
+}
+
+static xmlNodePtr
+xml_node_iter_get_current (xmlNodeIter *iter)
+{
+ return iter->cur_node;
+}
+
+static gint
+http_to_gio_error(guint status_code)
+{
+ switch (status_code)
+ {
+ case SOUP_STATUS_NOT_FOUND:
+ return G_IO_ERROR_NOT_FOUND;
+ break;
+ case SOUP_STATUS_UNAUTHORIZED:
+ case SOUP_STATUS_PAYMENT_REQUIRED:
+ case SOUP_STATUS_FORBIDDEN:
+ return G_IO_ERROR_PERMISSION_DENIED;
+ break;
+ case SOUP_STATUS_REQUEST_TIMEOUT:
+ return G_IO_ERROR_TIMED_OUT;
+ break;
+ case SOUP_STATUS_CANT_RESOLVE:
+ return G_IO_ERROR_HOST_NOT_FOUND;
+ break;
+ case SOUP_STATUS_NOT_IMPLEMENTED:
+ return G_IO_ERROR_NOT_SUPPORTED;
+ break;
+ case SOUP_STATUS_INSUFFICIENT_STORAGE:
+ return G_IO_ERROR_NO_SPACE;
+ break;
+ }
+
+ return G_IO_ERROR_FAILED;
+}
+
+static xmlDocPtr
+parse_xml (SoupMessage *msg,
+ xmlNodePtr *root,
+ const char *name,
+ GError **error)
+{
+ xmlDocPtr doc;
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ g_set_error (error, G_IO_ERROR, http_to_gio_error (msg->status_code),
+ _("HTTP Error: %s"), msg->reason_phrase);
+ return NULL;
+ }
+
+ doc = xmlReadMemory (msg->response_body->data,
+ msg->response_body->length,
+ "response.xml",
+ NULL,
+ XML_PARSE_NONET |
+ XML_PARSE_NOWARNING |
+ XML_PARSE_NOBLANKS |
+ XML_PARSE_NSCLEAN |
+ XML_PARSE_NOCDATA |
+ XML_PARSE_COMPACT);
+ if (doc == NULL)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Could not parse response"));
+ return NULL;
+ }
+
+ *root = xmlDocGetRootElement (doc);
+
+ if (*root == NULL || (*root)->children == NULL)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Empty response"));
+ xmlFreeDoc (doc);
+ return NULL;
+ }
+
+ if (strcmp ((char *) (*root)->name, name))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unexpected reply from server"));
+ xmlFreeDoc (doc);
+ return NULL;
+ }
+
+ return doc;
+}
+
+/* ************************************************************************* */
+/* Multistatus parsing code */
+
+typedef struct _Multistatus Multistatus;
+typedef struct _MsResponse MsResponse;
+typedef struct _MsPropstat MsPropstat;
+
+struct _Multistatus {
+
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
+ SoupURI *target;
+
+};
+
+struct _MsResponse {
+
+ Multistatus *multistatus;
+
+ xmlNodePtr href;
+ xmlNodePtr first_propstat;
+};
+
+struct _MsPropstat {
+
+ Multistatus *multistatus;
+
+ xmlNodePtr prop_node;
+ guint status_code;
+
+};
+
+
+static gboolean
+multistatus_parse (SoupMessage *msg, Multistatus *multistatus, GError **error)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
+ doc = parse_xml (msg, &root, "multistatus", error);
+
+ if (doc == NULL)
+ return FALSE;
+
+ multistatus->doc = doc;
+ multistatus->root = root;
+ multistatus->target = soup_message_get_uri (msg);
+
+ return TRUE;
+}
+
+static void
+multistatus_free (Multistatus *multistatus)
+{
+ xmlFreeDoc (multistatus->doc);
+}
+
+static void
+multistatus_get_response_iter (Multistatus *multistatus, xmlNodeIter *iter)
+{
+ iter->cur_node = multistatus->root->children;
+ iter->next_node = multistatus->root->children;
+ iter->name = "response";
+ iter->ns_href = "DAV:";
+ iter->user_data = multistatus;
+}
+
+static gboolean
+multistatus_get_response (xmlNodeIter *resp_iter, MsResponse *response)
+{
+ Multistatus *multistatus;
+ xmlNodePtr resp_node;
+ xmlNodePtr iter;
+ xmlNodePtr href;
+ xmlNodePtr propstat;
+
+ multistatus = xml_node_iter_get_user_data (resp_iter);
+ resp_node = xml_node_iter_get_current (resp_iter);
+
+ if (resp_node == NULL)
+ return FALSE;
+
+ propstat = NULL;
+ href = NULL;
+
+ for (iter = resp_node->children; iter; iter = iter->next)
+ {
+ if (! node_is_element (iter))
+ {
+ continue;
+ }
+ else if (node_has_name_ns (iter, "href", "DAV:"))
+ {
+ href = iter;
+ }
+ else if (node_has_name_ns (iter, "propstat", "DAV:"))
+ {
+ if (propstat == NULL)
+ propstat = iter;
+ }
+
+ if (href && propstat)
+ break;
+ }
+
+ if (href == NULL)
+ return FALSE;
+
+ response->href = href;
+ response->multistatus = multistatus;
+ response->first_propstat = propstat;
+
+ return resp_node != NULL;
+}
+
+static char *
+ms_response_get_basename (MsResponse *response)
+{
+ const char *text;
+ text = node_get_content (response->href);
+
+ return http_uri_get_basename (text);
+
+}
+
+static gboolean
+ms_response_is_target (MsResponse *response)
+{
+ const char *text;
+ const char *path;
+ SoupURI *target;
+ SoupURI *uri;
+ gboolean res;
+
+ uri = NULL;
+ path = NULL;
+ target = response->multistatus->target;
+ text = node_get_content (response->href);
+
+ if (text == NULL)
+ return FALSE;
+
+ uri = soup_uri_new_with_base (target, text);
+
+ if (uri == NULL)
+ return FALSE;
+
+ res = dav_uri_match (uri, target, TRUE);
+
+ soup_uri_free (uri);
+
+ return res;
+}
+
+static void
+ms_response_get_propstat_iter (MsResponse *response, xmlNodeIter *iter)
+{
+ iter->cur_node = response->first_propstat;
+ iter->next_node = response->first_propstat;
+ iter->name = "propstat";
+ iter->ns_href = "DAV:";
+ iter->user_data = response;
+}
+
+static guint
+ms_response_get_propstat (xmlNodeIter *cur_node, MsPropstat *propstat)
+{
+ MsResponse *response;
+ xmlNodePtr pstat_node;
+ xmlNodePtr iter;
+ xmlNodePtr prop;
+ xmlNodePtr status;
+ const char *status_text;
+ gboolean res;
+ guint code;
+
+ response = xml_node_iter_get_user_data (cur_node);
+ pstat_node = xml_node_iter_get_current (cur_node);
+
+ if (pstat_node == NULL)
+ return 0;
+
+ status = NULL;
+ prop = NULL;
+
+ for (iter = pstat_node->children; iter; iter = iter->next)
+ {
+ if (!node_is_element (iter))
+ {
+ continue;
+ }
+ else if (node_has_name_ns (iter, "status", "DAV:"))
+ {
+ status = iter;
+ }
+ else if (node_has_name_ns (iter, "prop", "DAV:"))
+ {
+ prop = iter;
+ }
+
+ if (status && prop)
+ break;
+ }
+
+ status_text = node_get_content (status);
+
+ if (status_text == NULL || prop == NULL)
+ return 0;
+
+ res = soup_headers_parse_status_line ((char *) status_text,
+ NULL,
+ &code,
+ NULL);
+
+ if (res == FALSE)
+ return 0;
+
+ propstat->prop_node = prop;
+ propstat->status_code = code;
+ propstat->multistatus = response->multistatus;
+
+ return code;
+}
+
+static GFileType
+parse_resourcetype (xmlNodePtr rt)
+{
+ xmlNodePtr node;
+ GFileType type;
+
+ for (node = rt->children; node; node = node->next)
+ {
+ if (node_is_element (node))
+ break;
+ }
+
+ if (node == NULL)
+ return G_FILE_TYPE_REGULAR;
+
+ if (! strcmp ((char *) node->name, "collection"))
+ type = G_FILE_TYPE_DIRECTORY;
+ else if (! strcmp ((char *) node->name, "redirectref"))
+ type = G_FILE_TYPE_SYMBOLIC_LINK;
+ else
+ type = G_FILE_TYPE_UNKNOWN;
+
+ return type;
+}
+
+static inline void
+file_info_set_content_type (GFileInfo *info, const char *type)
+{
+ g_file_info_set_content_type (info, type);
+ g_file_info_set_attribute_string (info,
+ G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
+ type);
+
+}
+
+static void
+ms_response_to_file_info (MsResponse *response,
+ GFileInfo *info)
+{
+ xmlNodeIter iter;
+ MsPropstat propstat;
+ xmlNodePtr node;
+ guint status;
+ char *basename;
+ const char *text;
+ GTimeVal tv;
+ GFileType file_type;
+ char *mime_type;
+ GIcon *icon;
+ gboolean have_display_name;
+
+ basename = ms_response_get_basename (response);
+ g_file_info_set_name (info, basename);
+ g_file_info_set_edit_name (info, basename);
+
+ file_type = G_FILE_TYPE_UNKNOWN;
+ mime_type = NULL;
+
+ have_display_name = FALSE;
+ ms_response_get_propstat_iter (response, &iter);
+ while (xml_node_iter_next (&iter))
+ {
+ status = ms_response_get_propstat (&iter, &propstat);
+
+ if (! SOUP_STATUS_IS_SUCCESSFUL (status))
+ continue;
+
+ for (node = propstat.prop_node->children; node; node = node->next)
+ {
+ if (! node_is_element (node))
+ continue; /* TODO: check namespace, parse user data nodes*/
+
+ text = node_get_content (node);
+
+ if (node_has_name (node, "resourcetype"))
+ {
+ file_type = parse_resourcetype (node);
+ g_file_info_set_file_type (info, file_type);
+ }
+ else if (node_has_name (node, "displayname"))
+ {
+ g_file_info_set_display_name (info, text);
+ have_display_name = TRUE;
+ }
+ else if (node_has_name (node, "getetag"))
+ {
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE,
+ text);
+ }
+ else if (node_has_name (node, "creationdate"))
+ {
+ if (! g_time_val_from_iso8601 (text, &tv))
+ continue;
+
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_CREATED,
+ tv.tv_sec);
+ }
+ else if (node_has_name (node, "getcontenttype"))
+ {
+ mime_type = g_strdup (text);
+ }
+ else if (node_has_name (node, "getcontentlength"))
+ {
+ gint64 size;
+ size = g_ascii_strtoll (text, NULL, 10);
+ g_file_info_set_size (info, size);
+ }
+ else if (node_has_name (node, "getlastmodified"))
+ {
+ SoupDate *sd;
+ GTimeVal tv;
+ sd = soup_date_new_from_string(text);
+ if (sd)
+ {
+ soup_date_to_timeval (sd, &tv);
+ g_file_info_set_modification_time (info, &tv);
+ soup_date_free (sd);
+ }
+ }
+ }
+ }
+
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ icon = g_themed_icon_new ("folder");
+ file_info_set_content_type (info, "inode/directory");
+ }
+ else
+ {
+ if (mime_type == NULL)
+ mime_type = g_content_type_guess (basename, NULL, 0, NULL);
+
+ icon = g_content_type_get_icon (mime_type);
+
+ if (G_IS_THEMED_ICON (icon))
+ g_themed_icon_append_name (G_THEMED_ICON (icon), "text-x-generic");
+
+ file_info_set_content_type (info, mime_type);
+ }
+
+ if (have_display_name == FALSE)
+ g_file_info_set_display_name (info, basename);
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_free (mime_type);
+ g_free (basename);
+
+}
+
+static GFileType
+ms_response_to_file_type (MsResponse *response)
+{
+ xmlNodeIter prop_iter;
+ MsPropstat propstat;
+ GFileType file_type;
+ guint status;
+
+ file_type = G_FILE_TYPE_UNKNOWN;
+
+ ms_response_get_propstat_iter (response, &prop_iter);
+ while (xml_node_iter_next (&prop_iter))
+ {
+ xmlNodePtr iter;
+
+ status = ms_response_get_propstat (&prop_iter, &propstat);
+
+ if (! SOUP_STATUS_IS_SUCCESSFUL (status))
+ continue;
+
+ for (iter = propstat.prop_node->children; iter; iter = iter->next)
+ {
+ if (node_is_element (iter) &&
+ node_has_name_ns (iter, "resourcetype", "DAV:"))
+ break;
+ }
+
+ if (iter)
+ {
+ file_type = parse_resourcetype (iter);
+ break;
+ }
+ }
+
+ return file_type;
+}
+
+#define PROPSTAT_XML_BEGIN \
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" \
+ " <D:propfind xmlns:D=\"DAV:\">\n"
+
+#define PROPSTAT_XML_ALLPROP " <D:allprop/>\n"
+#define PROPSTAT_XML_PROP_BEGIN " <D:prop>\n"
+#define PROPSTAT_XML_PROP_END " </D:prop>\n"
+
+#define PROPSTAT_XML_END \
+ " </D:propfind>"
+
+typedef struct _PropName {
+
+ const char *name;
+ const char *namespace;
+
+} PropName;
+
+
+static SoupMessage *
+propfind_request_new (GVfsBackend *backend,
+ const char *filename,
+ guint depth,
+ const PropName *properties)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+ const char *header_depth;
+ GString *body;
+
+ uri = http_backend_uri_for_filename (backend, filename, depth > 0);
+ msg = soup_message_new_from_uri (SOUP_METHOD_PROPFIND, uri);
+ soup_uri_free (uri);
+
+ if (msg == NULL)
+ return NULL;
+
+ if (depth == 0)
+ header_depth = "0";
+ else if (depth == 1)
+ header_depth = "1";
+ else
+ header_depth = "infinity";
+
+ soup_message_headers_append (msg->request_headers, "Depth", header_depth);
+
+ body = g_string_new (PROPSTAT_XML_BEGIN);
+
+ if (properties != NULL)
+ {
+ const PropName *prop;
+ g_string_append (body, PROPSTAT_XML_PROP_BEGIN);
+
+ for (prop = properties; prop->name; prop++)
+ {
+ if (prop->namespace != NULL)
+ g_string_append_printf (body, "<%s xmlns=\"%s\"/>\n",
+ prop->name,
+ prop->namespace);
+ else
+ g_string_append_printf (body, "<D:%s/>\n", prop->name);
+ }
+ g_string_append (body, PROPSTAT_XML_PROP_END);
+ }
+ else
+ g_string_append (body, PROPSTAT_XML_ALLPROP);
+
+
+ g_string_append (body, PROPSTAT_XML_END);
+
+ soup_message_set_request (msg, "application/xml",
+ SOUP_MEMORY_TAKE,
+ body->str,
+ body->len);
+
+ g_string_free (body, FALSE);
+
+ return msg;
+}
+
+static SoupMessage *
+stat_location_begin (SoupURI *uri,
+ gboolean count_children)
+{
+ SoupMessage *msg;
+ const char *depth;
+ static const char *stat_profind_body =
+ PROPSTAT_XML_BEGIN
+ PROPSTAT_XML_PROP_BEGIN
+ "<D:resourcetype/>\n"
+ PROPSTAT_XML_PROP_END
+ PROPSTAT_XML_END;
+
+ msg = soup_message_new_from_uri (SOUP_METHOD_PROPFIND, uri);
+
+ if (count_children)
+ depth = "1";
+ else
+ depth = "0";
+
+ soup_message_headers_append (msg->request_headers, "Depth", depth);
+
+ soup_message_set_request (msg, "application/xml",
+ SOUP_MEMORY_STATIC,
+ stat_profind_body,
+ strlen (stat_profind_body));
+ return msg;
+}
+
+static gboolean
+stat_location_finish (SoupMessage *msg,
+ GFileType *target_type,
+ guint *num_children)
+{
+ Multistatus ms;
+ xmlNodeIter iter;
+ gboolean res;
+ GError *error;
+ guint child_count;
+ GFileType file_type;
+
+ if (msg->status_code != 207)
+ return FALSE;
+
+ res = multistatus_parse (msg, &ms, &error);
+
+ if (res == FALSE)
+ return FALSE;
+
+ res = FALSE;
+ child_count = 0;
+ file_type = G_FILE_TYPE_UNKNOWN;
+
+ multistatus_get_response_iter (&ms, &iter);
+ while (xml_node_iter_next (&iter))
+ {
+ MsResponse response;
+
+ if (! multistatus_get_response (&iter, &response))
+ continue;
+
+ if (ms_response_is_target (&response))
+ {
+ file_type = ms_response_to_file_type (&response);
+ res = TRUE;
+ }
+ else
+ child_count++;
+ }
+
+ if (res)
+ {
+ if (target_type)
+ *target_type = file_type;
+
+ if (num_children)
+ *num_children = child_count;
+ }
+
+ multistatus_free (&ms);
+ return res;
+}
+
+static gboolean
+stat_location (GVfsBackend *backend,
+ SoupURI *uri,
+ GFileType *target_type,
+ guint *num_children,
+ GError **error)
+{
+ SoupMessage *msg;
+ guint status;
+ gboolean count_children;
+ gboolean res;
+
+ count_children = num_children != NULL;
+ msg = stat_location_begin (uri, count_children);
+
+ if (msg == NULL)
+ return FALSE;
+
+ status = g_vfs_backend_dav_send_message (backend, msg);
+
+ if (status != 207)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ http_error_code_from_status (status),
+ msg->reason_phrase);
+
+ return FALSE;
+ }
+
+ res = stat_location_finish (msg, target_type, num_children);
+
+ if (res == FALSE)
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Response invalid"));
+
+ return res;
+}
+
+
+/* ************************************************************************* */
+/* Authentication */
+
+static void
+mount_auth_info_free (MountAuthData *data)
+{
+ if (data->mount_source)
+ g_object_unref (data->mount_source);
+
+ g_free (data->server_auth.username);
+ g_free (data->server_auth.password);
+ g_free (data->server_auth.realm);
+
+ g_free (data->proxy_auth.username);
+ g_free (data->proxy_auth.password);
+
+}
+
+static void
+soup_authenticate_from_data (SoupSession *session,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying,
+ gpointer user_data)
+{
+ MountAuthData *data;
+ AuthInfo *info;
+
+ g_debug ("+ soup_authenticate_from_data (%s) \n",
+ retrying ? "retrying" : "first auth");
+
+ if (retrying)
+ return;
+
+ data = (MountAuthData *) user_data;
+
+ if (soup_auth_is_for_proxy (auth))
+ info = &data->proxy_auth;
+ else
+ info = &data->server_auth;
+
+ soup_auth_authenticate (auth, info->username, info->password);
+}
+
+static void
+soup_authenticate_interactive (SoupSession *session,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying,
+ gpointer user_data)
+{
+ MountAuthData *data;
+ AuthInfo *info;
+ GAskPasswordFlags pw_ask_flags;
+ GPasswordSave pw_save;
+ const char *realm;
+ gboolean res;
+ gboolean aborted;
+ gboolean is_proxy;
+ gboolean have_auth;
+ char *new_username;
+ char *new_password;
+ char *prompt;
+
+ g_debug ("+ soup_authenticate_interactive (%s) \n",
+ retrying ? "retrying" : "first auth");
+
+ data = (MountAuthData *) user_data;
+
+ new_username = NULL;
+ new_password = NULL;
+ realm = NULL;
+ pw_ask_flags = G_ASK_PASSWORD_NEED_PASSWORD;
+
+ is_proxy = soup_auth_is_for_proxy (auth);
+ realm = soup_auth_get_realm (auth);
+
+ if (is_proxy)
+ info = &(data->proxy_auth);
+ else
+ info = &(data->server_auth);
+
+ if (realm && info->realm == NULL)
+ info->realm = g_strdup (realm);
+ else if (realm && info->realm && !g_str_equal (realm, info->realm))
+ return;
+
+ have_auth = info->username && info->password;
+
+ if (have_auth == FALSE && g_vfs_keyring_is_available ())
+ {
+ SoupURI *uri;
+ SoupURI *uri_free = NULL;
+
+ pw_ask_flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+
+ if (is_proxy)
+ {
+ g_object_get (session, SOUP_SESSION_PROXY_URI, &uri_free, NULL);
+ uri = uri_free;
+ }
+ else
+ uri = soup_message_get_uri (msg);
+
+ res = g_vfs_keyring_lookup_password (info->username,
+ uri->host,
+ NULL,
+ "http",
+ realm,
+ is_proxy ? "proxy" : "basic",
+ uri->port,
+ &new_username,
+ NULL,
+ &new_password);
+
+ if (res == TRUE)
+ {
+ have_auth = TRUE;
+ g_free (info->username);
+ g_free (info->password);
+ info->username = new_username;
+ info->password = new_password;
+ }
+
+ if (uri_free)
+ soup_uri_free (uri_free);
+ }
+
+ if (retrying == FALSE && have_auth)
+ {
+ soup_auth_authenticate (auth, info->username, info->password);
+ return;
+ }
+
+ if (is_proxy == FALSE)
+ {
+ if (realm == NULL)
+ realm = _("WebDAV share");
+
+ prompt = g_strdup_printf (_("Enter password for %s"), realm);
+ }
+ else
+ prompt = g_strdup (_("Please enter proxy password"));
+
+ if (info->username == NULL)
+ pw_ask_flags |= G_ASK_PASSWORD_NEED_USERNAME;
+
+ res = g_mount_source_ask_password (data->mount_source,
+ prompt,
+ info->username,
+ NULL,
+ pw_ask_flags,
+ &aborted,
+ &new_password,
+ &new_username,
+ NULL,
+ NULL,
+ &pw_save);
+
+ if (res && !aborted)
+ {
+ soup_auth_authenticate (auth, new_username, new_password);
+
+ g_free (info->username);
+ g_free (info->password);
+ info->username = new_username;
+ info->password = new_password;
+ info->pw_save = pw_save;
+ }
+ else
+ soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED);
+
+ g_debug ("- soup_authenticate \n");
+ g_free (prompt);
+}
+
+static void
+keyring_save_authinfo (AuthInfo *info,
+ SoupURI *uri,
+ gboolean is_proxy)
+{
+ const char *type = is_proxy ? "proxy" : "basic";
+
+ g_vfs_keyring_save_password (info->username,
+ uri->host,
+ NULL,
+ "http",
+ info->realm,
+ type,
+ uri->port,
+ info->password,
+ info->pw_save);
+}
+
+/* ************************************************************************* */
+
+static SoupURI *
+g_mount_spec_to_dav_uri (GMountSpec *spec)
+{
+ SoupURI *uri;
+ const char *host;
+ const char *user;
+ const char *port;
+ const char *ssl;
+ gint port_num;
+
+ host = g_mount_spec_get (spec, "host");
+ user = g_mount_spec_get (spec, "user");
+ port = g_mount_spec_get (spec, "port");
+ ssl = g_mount_spec_get (spec, "ssl");
+
+ if (host == NULL || *host == 0)
+ return NULL;
+
+ uri = soup_uri_new (NULL);
+
+ if (ssl != NULL && (strcmp (ssl, "true") == 0))
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
+ else
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
+
+ soup_uri_set_user (uri, user);
+
+ if (port && (port_num = atoi (port)))
+ soup_uri_set_port (uri, port_num);
+
+ soup_uri_set_host (uri, host);
+ soup_uri_set_path (uri, spec->mount_prefix);
+
+ return uri;
+}
+
+static GMountSpec *
+g_mount_spec_from_dav_uri (GVfsBackendDav *dav_backend,
+ SoupURI *uri)
+{
+ GMountSpec *spec;
+ const char *ssl;
+
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ {
+ const char *type;
+ const char *service_type;
+
+ service_type = g_vfs_dns_sd_resolver_get_service_type (dav_backend->resolver);
+ if (strcmp (service_type, "_webdavs._tcp") == 0)
+ type = "davs+sd";
+ else
+ type = "dav+sd";
+
+ spec = g_mount_spec_new (type);
+ g_mount_spec_set (spec,
+ "host",
+ g_vfs_dns_sd_resolver_get_encoded_triple (dav_backend->resolver));
+ return spec;
+ }
+#endif
+
+ spec = g_mount_spec_new ("dav");
+
+ g_mount_spec_set (spec, "host", uri->host);
+
+ if (uri->scheme == SOUP_URI_SCHEME_HTTPS)
+ ssl = "true";
+ else
+ ssl = "false";
+
+ g_mount_spec_set (spec, "ssl", ssl);
+
+ if (uri->user)
+ g_mount_spec_set (spec, "user", uri->user);
+
+ if (! soup_uri_uses_default_port (uri))
+ {
+ char *port = g_strdup_printf ("%u", uri->port);
+ g_mount_spec_set (spec, "port", port);
+ g_free (port);
+ }
+
+ g_mount_spec_set_mount_prefix (spec, uri->path);
+
+ return spec;
+}
+
+#ifdef HAVE_AVAHI
+static SoupURI *
+dav_uri_from_dns_sd_resolver (GVfsBackendDav *dav_backend)
+{
+ SoupURI *uri;
+ char *user;
+ char *path;
+ char *address;
+ const char *service_type;
+ guint port;
+
+ service_type = g_vfs_dns_sd_resolver_get_service_type (dav_backend->resolver);
+ address = g_vfs_dns_sd_resolver_get_address (dav_backend->resolver);
+ port = g_vfs_dns_sd_resolver_get_port (dav_backend->resolver);
+ user = g_vfs_dns_sd_resolver_lookup_txt_record (dav_backend->resolver, "u"); /* mandatory */
+ path = g_vfs_dns_sd_resolver_lookup_txt_record (dav_backend->resolver, "path"); /* optional */
+
+ /* TODO: According to http://www.dns-sd.org/ServiceTypes.html
+ * there's also a TXT record "p" for password. Handle this.
+ */
+
+ uri = soup_uri_new (NULL);
+
+ if (strcmp (service_type, "_webdavs._tcp") == 0)
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
+ else
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
+
+ soup_uri_set_user (uri, user);
+
+ soup_uri_set_port (uri, port);
+
+ soup_uri_set_host (uri, address);
+
+ if (path != NULL)
+ soup_uri_set_path (uri, path);
+ else
+ soup_uri_set_path (uri, "/");
+
+
+ g_free (address);
+ g_free (user);
+ g_free (path);
+
+ return uri;
+}
+#endif
+
+#ifdef HAVE_AVAHI
+static void
+dns_sd_resolver_changed (GVfsDnsSdResolver *resolver,
+ GVfsBackendDav *dav_backend)
+{
+ /* TODO: handle when DNS-SD data changes */
+}
+#endif
+
+/* ************************************************************************* */
+/* Backend Functions */
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (backend);
+ MountAuthData *data;
+ SoupSession *session;
+ SoupMessage *msg_opts;
+ SoupMessage *msg_stat;
+ SoupURI *mount_base;
+ gulong signal_id;
+ guint status;
+ gboolean is_success;
+ gboolean is_webdav;
+ gboolean res;
+ char *last_good_path;
+ char *display_name;
+ const char *host;
+ const char *type;
+
+ g_debug ("+ mount\n");
+
+ host = g_mount_spec_get (mount_spec, "host");
+ type = g_mount_spec_get (mount_spec, "type");
+
+#ifdef HAVE_AVAHI
+ /* resolve DNS-SD style URIs */
+ if ((strcmp (type, "dav+sd") == 0 || strcmp (type, "davs+sd") == 0) && host != NULL)
+ {
+ GError *error;
+
+ dav_backend->resolver = g_vfs_dns_sd_resolver_new_for_encoded_triple (host, "u");
+
+ error = NULL;
+ if (!g_vfs_dns_sd_resolver_resolve_sync (dav_backend->resolver,
+ NULL,
+ &error))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_signal_connect (dav_backend->resolver,
+ "changed",
+ (GCallback) dns_sd_resolver_changed,
+ dav_backend);
+
+ mount_base = dav_uri_from_dns_sd_resolver (dav_backend);
+ }
+ else
+#endif
+ {
+ mount_base = g_mount_spec_to_dav_uri (mount_spec);
+ }
+
+ if (mount_base == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+
+ session = G_VFS_BACKEND_HTTP (backend)->session;
+ G_VFS_BACKEND_HTTP (backend)->mount_base = mount_base;
+
+ data = &(G_VFS_BACKEND_DAV (backend)->auth_info);
+ data->mount_source = g_object_ref (mount_source);
+ data->server_auth.username = g_strdup (mount_base->user);
+ data->server_auth.pw_save = G_PASSWORD_SAVE_NEVER;
+ data->proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER;
+
+ signal_id = g_signal_connect (session, "authenticate",
+ G_CALLBACK (soup_authenticate_interactive),
+ data);
+
+ last_good_path = NULL;
+ msg_opts = soup_message_new_from_uri (SOUP_METHOD_OPTIONS, mount_base);
+ msg_stat = stat_location_begin (mount_base, FALSE);
+
+ do {
+ status = g_vfs_backend_dav_send_message (backend, msg_opts);
+
+ is_success = SOUP_STATUS_IS_SUCCESSFUL (status);
+ is_webdav = is_success && sm_has_header (msg_opts, "DAV");
+
+ soup_message_headers_clear (msg_opts->response_headers);
+ soup_message_body_truncate (msg_opts->response_body);
+
+ if (is_webdav)
+ {
+ GFileType file_type;
+ SoupURI *cur_uri;
+
+ cur_uri = soup_message_get_uri (msg_opts);
+ soup_message_set_uri (msg_stat, cur_uri);
+
+ g_vfs_backend_dav_send_message (backend, msg_stat);
+ res = stat_location_finish (msg_stat, &file_type, NULL);
+
+ if (res && file_type == G_FILE_TYPE_DIRECTORY)
+ {
+ g_free (last_good_path);
+ last_good_path = mount_base->path;
+ }
+
+ mount_base->path = path_get_parent_dir (mount_base->path);
+ soup_message_set_uri (msg_opts, mount_base);
+
+ soup_message_headers_clear (msg_stat->response_headers);
+ soup_message_body_truncate (msg_stat->response_body);
+ }
+
+ } while (is_webdav && mount_base->path != NULL);
+
+ /* we have reached the end of paths we are allowed to
+ * chdir up to (or couldn't chdir up at all) */
+
+ /* check if we at all have a good path */
+ if (last_good_path == NULL)
+ {
+
+ /* TODO: set correct error in case of cancellation */
+ if (!is_success)
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("HTTP Error: %s"), msg_opts->reason_phrase);
+ else if (!is_webdav)
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Not a WebDAV enabled share"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Not a WebDAV enabled share"));
+
+ /* TODO: We leak a bunch of stuff here :-( */
+ /* TODO: STRING CHANGE: change to: Could not find an enclosing directory */
+ return;
+ }
+
+ /* Success! We are mounted */
+ /* Save the auth info in the keyring */
+
+ keyring_save_authinfo (&(data->server_auth), mount_base, FALSE);
+ /* TODO: save proxy auth */
+
+ /* Set the working path in mount path */
+ g_free (mount_base->path);
+ mount_base->path = last_good_path;
+
+ /* dup the mountspec, but only copy known fields */
+ mount_spec = g_mount_spec_from_dav_uri (dav_backend, mount_base);
+
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_vfs_backend_set_icon_name (backend, "folder-remote");
+
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ display_name = g_strdup (g_vfs_dns_sd_resolver_get_service_name (dav_backend->resolver));
+ else
+#endif
+ display_name = g_strdup_printf (_("WebDAV on %s"), mount_base->host);
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+
+ /* cleanup */
+ g_mount_spec_unref (mount_spec);
+ g_object_unref (msg_opts);
+ g_object_unref (msg_stat);
+
+ /* switch the signal handler */
+ g_signal_handler_disconnect (session, signal_id);
+ g_signal_connect (session, "authenticate",
+ G_CALLBACK (soup_authenticate_from_data),
+ data);
+
+ /* also auth the workaround async session we need for SoupInputStream */
+ g_signal_connect (G_VFS_BACKEND_HTTP (backend)->session_async, "authenticate",
+ G_CALLBACK (soup_authenticate_from_data),
+ data);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_debug ("- mount\n");
+}
+
+static PropName ls_propnames[] = {
+ {"creationdate", NULL},
+ {"displayname", NULL},
+ {"getcontentlength", NULL},
+ {"getcontenttype", NULL},
+ {"getetag", NULL},
+ {"getlastmodified", NULL},
+ {"resourcetype", NULL},
+ {NULL, NULL}
+};
+
+/* *** query_info () *** */
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ SoupMessage *msg;
+ Multistatus ms;
+ xmlNodeIter iter;
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+
+ g_debug ("Query info %s\n", filename);
+
+ msg = propfind_request_new (backend, filename, 0, ls_propnames);
+
+ if (msg == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Could not create request"));
+
+ return;
+ }
+
+ message_add_redirect_header (msg, flags);
+
+ g_vfs_backend_dav_send_message (backend, msg);
+
+ res = multistatus_parse (msg, &ms, &error);
+
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_object_unref (msg);
+ return;
+ }
+
+ res = FALSE;
+ multistatus_get_response_iter (&ms, &iter);
+
+ while (xml_node_iter_next (&iter))
+ {
+ MsResponse response;
+
+ if (! multistatus_get_response (&iter, &response))
+ continue;
+
+ if (ms_response_is_target (&response))
+ {
+ ms_response_to_file_info (&response, job->file_info);
+ res = TRUE;
+ }
+ }
+
+ multistatus_free (&ms);
+ g_object_unref (msg);
+
+ if (res)
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Response invalid"));
+
+}
+
+
+/* *** enumerate *** */
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ SoupMessage *msg;
+ Multistatus ms;
+ xmlNodeIter iter;
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+
+ g_debug ("+ do_enumerate: %s\n", filename);
+
+ msg = propfind_request_new (backend, filename, 1, ls_propnames);
+
+ if (msg == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Could not create request"));
+
+ return;
+ }
+
+ message_add_redirect_header (msg, flags);
+
+ g_vfs_backend_dav_send_message (backend, msg);
+
+ res = multistatus_parse (msg, &ms, &error);
+
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_object_unref (msg);
+ return;
+ }
+
+ multistatus_get_response_iter (&ms, &iter);
+
+ while (xml_node_iter_next (&iter))
+ {
+ MsResponse response;
+ GFileInfo *info;
+
+ if (! multistatus_get_response (&iter, &response))
+ continue;
+
+ if (ms_response_is_target (&response))
+ continue;
+
+ info = g_file_info_new ();
+ ms_response_to_file_info (&response, info);
+ g_vfs_job_enumerate_add_info (job, info);
+ }
+
+ multistatus_free (&ms);
+ g_object_unref (msg);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job)); /* should that be called earlier? */
+ g_vfs_job_enumerate_done (G_VFS_JOB_ENUMERATE (job));
+}
+
+/* ************************************************************************* */
+/* */
+
+/* *** create () *** */
+static void
+try_create_tested_existence (SoupSession *session, SoupMessage *msg,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (user_data);
+ GVfsBackendHttp *op_backend = job->backend_data;
+ GOutputStream *stream;
+ SoupMessage *put_msg;
+ SoupURI *uri;
+
+ if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ g_vfs_job_failed (job,
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ return;
+ }
+ /* TODO: other errors */
+
+ uri = soup_message_get_uri (msg);
+ put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
+
+ /*
+ * Doesn't work with apache > 2.2.9
+ * soup_message_headers_append (put_msg->request_headers, "If-None-Match", "*");
+ */
+ stream = soup_output_stream_new (op_backend->session, put_msg, -1);
+ g_object_unref (put_msg);
+
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+
+ /* TODO: if SoupOutputStream supported chunked requests, we could
+ * use a PUT with "If-None-Match: *" and "Expect: 100-continue"
+ */
+ uri = http_backend_uri_for_filename (backend, filename, FALSE);
+ msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri);
+ soup_uri_free (uri);
+
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), backend, NULL);
+
+ http_backend_queue_message (backend, msg, try_create_tested_existence, job);
+ return TRUE;
+}
+
+/* *** replace () *** */
+static void
+open_for_replace_succeeded (GVfsBackendHttp *op_backend, GVfsJob *job,
+ SoupURI *uri, const char *etag)
+{
+ SoupMessage *put_msg;
+ GOutputStream *stream;
+
+ put_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
+
+ if (etag)
+ soup_message_headers_append (put_msg->request_headers, "If-Match", etag);
+
+ stream = soup_output_stream_new (op_backend->session, put_msg, -1);
+ g_object_unref (put_msg);
+
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), stream);
+ g_vfs_job_succeeded (job);
+}
+
+static void
+try_replace_checked_etag (SoupSession *session, SoupMessage *msg,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (user_data);
+ GVfsBackendHttp *op_backend = job->backend_data;
+
+ if (msg->status_code == SOUP_STATUS_PRECONDITION_FAILED)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_WRONG_ETAG,
+ _("The file was externally modified"));
+ return;
+ }
+ /* TODO: other errors */
+
+ open_for_replace_succeeded (op_backend, job, soup_message_get_uri (msg),
+ soup_message_headers_get (msg->request_headers, "If-Match"));
+}
+
+static gboolean
+try_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GVfsBackendHttp *op_backend;
+ SoupURI *uri;
+
+ /* TODO: if SoupOutputStream supported chunked requests, we could
+ * use a PUT with "If-Match: ..." and "Expect: 100-continue"
+ */
+
+ op_backend = G_VFS_BACKEND_HTTP (backend);
+
+ if (make_backup)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("Backup file creation failed"));
+ return TRUE;
+ }
+
+
+
+ uri = http_backend_uri_for_filename (backend, filename, FALSE);
+
+ if (etag)
+ {
+ SoupMessage *msg;
+
+ msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri);
+ soup_uri_free (uri);
+ soup_message_headers_append (msg->request_headers, "If-Match", etag);
+
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), op_backend, NULL);
+ soup_session_queue_message (op_backend->session, msg,
+ try_replace_checked_etag, job);
+ return TRUE;
+ }
+
+ open_for_replace_succeeded (op_backend, G_VFS_JOB (job), uri, NULL);
+ soup_uri_free (uri);
+ return TRUE;
+}
+
+/* *** write () *** */
+static void
+write_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GOutputStream *stream;
+ GVfsJob *job;
+ GError *error;
+ gssize nwrote;
+
+ stream = G_OUTPUT_STREAM (source_object);
+ error = NULL;
+ job = G_VFS_JOB (user_data);
+
+ nwrote = g_output_stream_write_finish (stream, result, &error);
+
+ if (nwrote < 0)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ g_vfs_job_write_set_written_size (G_VFS_JOB_WRITE (job), nwrote);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ GOutputStream *stream;
+
+ stream = G_OUTPUT_STREAM (handle);
+
+ g_output_stream_write_async (stream,
+ buffer,
+ buffer_size,
+ G_PRIORITY_DEFAULT,
+ G_VFS_JOB (job)->cancellable,
+ write_ready,
+ job);
+ return TRUE;
+}
+
+/* *** close_write () *** */
+static void
+close_write_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GOutputStream *stream;
+ GVfsJob *job;
+ GError *error;
+ gboolean res;
+
+ error = NULL;
+ job = G_VFS_JOB (user_data);
+ stream = G_OUTPUT_STREAM (source_object);
+ res = g_output_stream_close_finish (stream,
+ result,
+ &error);
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+
+ g_error_free (error);
+ }
+ else
+ g_vfs_job_succeeded (job);
+
+ g_object_unref (stream);
+}
+
+static gboolean
+try_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle)
+{
+ GOutputStream *stream;
+
+ stream = G_OUTPUT_STREAM (handle);
+
+ g_output_stream_close_async (stream,
+ G_PRIORITY_DEFAULT,
+ G_VFS_JOB (job)->cancellable,
+ close_write_ready,
+ job);
+
+ return TRUE;
+}
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+ guint status;
+
+ uri = http_backend_uri_for_filename (backend, filename, TRUE);
+ msg = soup_message_new_from_uri (SOUP_METHOD_MKCOL, uri);
+ soup_uri_free (uri);
+
+ status = g_vfs_backend_dav_send_message (backend, msg);
+
+ if (! SOUP_STATUS_IS_SUCCESSFUL (status))
+ if (status == SOUP_STATUS_METHOD_NOT_ALLOWED)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ else
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ http_error_code_from_status (status),
+ msg->reason_phrase);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_object_unref (msg);
+}
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+ GFileType file_type;
+ gboolean res;
+ guint num_children;
+ guint status;
+ GError *error;
+
+ error = NULL;
+
+ uri = http_backend_uri_for_filename (backend, filename, FALSE);
+ res = stat_location (backend, uri, &file_type, &num_children, &error);
+
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (file_type == G_FILE_TYPE_DIRECTORY && num_children)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_EMPTY,
+ _("Directory not empty"));
+ return;
+ }
+
+ msg = soup_message_new_from_uri (SOUP_METHOD_DELETE, uri);
+
+ status = g_vfs_backend_dav_send_message (backend, msg);
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ G_IO_ERROR,
+ http_error_code_from_status (status),
+ msg->reason_phrase);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ soup_uri_free (uri);
+ g_object_unref (msg);
+}
+
+static void
+do_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ SoupMessage *msg;
+ SoupURI *source;
+ SoupURI *target;
+ char *target_path;
+ char *dirname;
+ guint status;
+
+ source = http_backend_uri_for_filename (backend, filename, FALSE);
+ msg = soup_message_new_from_uri (SOUP_METHOD_MOVE, source);
+
+ dirname = g_path_get_dirname (filename);
+ target_path = g_build_filename (dirname, display_name, NULL);
+ target = http_backend_uri_for_filename (backend, target_path, FALSE);
+
+ message_add_destination_header (msg, target);
+ message_add_overwrite_header (msg, FALSE);
+
+ status = g_vfs_backend_dav_send_message (backend, msg);
+
+ /*
+ * The precondition of SOUP_STATUS_PRECONDITION_FAILED (412) in
+ * this case was triggered by the "Overwrite: F" header which
+ * means that the target already exists.
+ * Also if we get a REDIRECTION it means that there was no
+ * "Location" header, since otherwise that would have triggered
+ * our redirection handler. This probably means we are dealing
+ * with an web dav implementation (like mod_dav) that also sends
+ * redirects for the destionaion (i.e. "Destination: /foo" header)
+ * which very likely means that the target also exists (and is a
+ * directory). That or the webdav server is broken.
+ * We could find out by doing another stat and but I think this is
+ * such a corner case that we are totally fine with returning
+ * G_IO_ERROR_EXISTS.
+ * */
+
+ if (SOUP_STATUS_IS_SUCCESSFUL (status))
+ {
+ g_debug ("new target_path: %s\n", target_path);
+ g_vfs_job_set_display_name_set_new_path (job, target_path);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else if (status == SOUP_STATUS_PRECONDITION_FAILED ||
+ SOUP_STATUS_IS_REDIRECTION (status))
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ http_error_code_from_status (status),
+ "%s", msg->reason_phrase);
+
+ g_object_unref (msg);
+ g_free (dirname);
+ g_free (target_path);
+ soup_uri_free (target);
+ soup_uri_free (source);
+}
+
+static gboolean
+try_unmount (GVfsBackend *backend,
+ GVfsJobUnmount *job)
+{
+ _exit (0);
+}
+
+/* ************************************************************************* */
+/* */
+static void
+g_vfs_backend_dav_class_init (GVfsBackendDavClass *klass)
+{
+ GObjectClass *gobject_class;
+ GVfsBackendClass *backend_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = g_vfs_backend_dav_finalize;
+
+ backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ backend_class->try_mount = NULL;
+ backend_class->mount = do_mount;
+ backend_class->try_query_info = NULL;
+ backend_class->query_info = do_query_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->try_create = try_create;
+ backend_class->try_replace = try_replace;
+ backend_class->try_write = try_write;
+ backend_class->try_close_write = try_close_write;
+ backend_class->make_directory = do_make_directory;
+ backend_class->delete = do_delete;
+ backend_class->set_display_name = do_set_display_name;
+ backend_class->try_unmount = try_unmount;
+}
diff --git a/trunk/daemon/gvfsbackenddav.h b/trunk/daemon/gvfsbackenddav.h
new file mode 100644
index 00000000..226e5dc0
--- /dev/null
+++ b/trunk/daemon/gvfsbackenddav.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_DAV_H__
+#define __G_VFS_BACKEND_DAV_H__
+
+#include <gvfsbackendhttp.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_DAV (g_vfs_backend_dav_get_type ())
+#define G_VFS_BACKEND_DAV(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_DAV, GVfsBackendDav))
+#define G_VFS_BACKEND_DAV_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_DAV, GVfsBackendDavClass))
+#define G_VFS_IS_BACKEND_DAV(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_DAV))
+#define G_VFS_IS_BACKEND_DAV_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_DAV))
+#define G_VFS_BACKEND_DAV_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_DAV, GVfsBackendDavClass))
+
+typedef struct _GVfsBackendDav GVfsBackendDav;
+typedef struct _GVfsBackendDavClass GVfsBackendDavClass;
+
+struct _GVfsBackendDavClass
+{
+ GVfsBackendHttpClass parent_class;
+};
+
+GType g_vfs_backend_dav_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_DAV_H__ */
diff --git a/trunk/daemon/gvfsbackenddnssd.c b/trunk/daemon/gvfsbackenddnssd.c
new file mode 100644
index 00000000..6950ef3f
--- /dev/null
+++ b/trunk/daemon/gvfsbackenddnssd.c
@@ -0,0 +1,800 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#include <avahi-common/timeval.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
+
+#include "gvfsbackenddnssd.h"
+#include "gvfsdnssdutils.h"
+
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsmonitor.h"
+
+static struct {
+ char *type;
+ char *method;
+ gboolean use_dns_sd_uri;
+ char *icon;
+} dns_sd_types[] = {
+ {
+ "_ftp._tcp",
+ "ftp",
+ FALSE,
+ "folder-remote-ftp"
+ },
+ {
+ "_webdav._tcp",
+ "dav+sd",
+ TRUE,
+ "folder-remote-dav"
+ },
+ {
+ "_webdavs._tcp",
+ "davs+sd",
+ TRUE,
+ "folder-remote-davs"},
+ {
+ "_sftp-ssh._tcp",
+ "sftp",
+ FALSE,
+ "folder-remote-ssh"
+ },
+ {
+ "_ssh._tcp",
+ "sftp",
+ FALSE,
+ "folder-remote-ssh"
+ },
+ {
+ "_smb._tcp",
+ "smb",
+ FALSE,
+ "network-server"
+ },
+};
+
+static AvahiClient *global_client = NULL;
+static gboolean avahi_initialized = FALSE;
+
+static GList *dnssd_backends = NULL;
+
+typedef struct {
+ char *file_name;
+ char *name;
+ char *type;
+ char *domain;
+ char *target_uri;
+
+ GIcon *icon;
+} LinkFile;
+
+static LinkFile root = { "/" };
+
+static gboolean resolver_supports_mdns = FALSE;
+
+struct _GVfsBackendDnsSd
+{
+ GVfsBackend parent_instance;
+ GVfsMonitor *root_monitor;
+ char *domain;
+ GMountSpec *mount_spec;
+ GList *files; /* list of LinkFiles */
+
+ GList *browsers;
+};
+
+typedef struct _GVfsBackendDnsSd GVfsBackendDnsSd;
+
+G_DEFINE_TYPE (GVfsBackendDnsSd, g_vfs_backend_dns_sd, G_VFS_TYPE_BACKEND)
+
+static void add_browsers (GVfsBackendDnsSd *backend);
+static void remove_browsers (GVfsBackendDnsSd *backend);
+static AvahiClient *get_global_avahi_client (void);
+
+/* Callback for state changes on the Client */
+static void
+avahi_client_callback (AvahiClient *client, AvahiClientState state, void *userdata)
+{
+ /* We need to set this early, as the add_browsers call below may reenter
+ when this is called from the client creation call */
+ if (global_client == NULL)
+ global_client = client;
+
+ if (state == AVAHI_CLIENT_FAILURE)
+ {
+ if (avahi_client_errno (client) == AVAHI_ERR_DISCONNECTED)
+ {
+ /* Remove the service browsers from the handles */
+ g_list_foreach (dnssd_backends, (GFunc)remove_browsers, NULL);
+
+ /* Destroy old client */
+ avahi_client_free (client);
+ global_client = NULL;
+ avahi_initialized = FALSE;
+
+ /* Reconnect */
+ get_global_avahi_client ();
+ }
+ }
+ else if (state == AVAHI_CLIENT_S_RUNNING)
+ {
+ /* Start browsing again */
+ g_list_foreach (dnssd_backends, (GFunc)add_browsers, NULL);
+ }
+}
+
+static AvahiClient *
+get_global_avahi_client (void)
+{
+ static AvahiGLibPoll *glib_poll = NULL;
+ int error;
+
+ if (!avahi_initialized)
+ {
+ avahi_initialized = TRUE;
+
+ if (glib_poll == NULL)
+ {
+ avahi_set_allocator (avahi_glib_allocator ());
+ glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
+ }
+
+ /* Create a new AvahiClient instance */
+ global_client = avahi_client_new (avahi_glib_poll_get (glib_poll),
+ AVAHI_CLIENT_NO_FAIL,
+ avahi_client_callback,
+ glib_poll,
+ &error);
+
+ if (global_client == NULL)
+ {
+ /* Print out the error string */
+ g_warning ("Error initializing Avahi: %s", avahi_strerror (error));
+ return NULL;
+ }
+ }
+
+ return global_client;
+}
+
+static GIcon *
+get_icon_for_type (const char *type)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
+ {
+ if (strcmp (type, dns_sd_types[i].type) == 0)
+ return g_themed_icon_new_with_default_fallbacks (dns_sd_types[i].icon);
+ }
+
+ return g_themed_icon_new ("text-x-generic");
+}
+
+static const char *
+get_method_for_type (const char *type)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
+ {
+ if (strcmp (type, dns_sd_types[i].type) == 0)
+ return dns_sd_types[i].method;
+ }
+
+ return NULL;
+}
+
+static gboolean
+use_dns_sd_uri_for_type (const char *type)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
+ {
+ if (strcmp (type, dns_sd_types[i].type) == 0)
+ return dns_sd_types[i].use_dns_sd_uri;
+ }
+
+ return FALSE;
+}
+
+static LinkFile *
+link_file_new (const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ AvahiProtocol protocol,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt)
+{
+ LinkFile *file;
+ char a[128];
+ const char *method;
+ char *uri;
+
+ file = g_slice_new0 (LinkFile);
+
+ file->name = g_strdup (name);
+ file->type = g_strdup (type);
+ file->domain = g_strdup (domain);
+ file->icon = get_icon_for_type (type);
+
+ uri = g_vfs_get_dns_sd_uri_for_triple (name, type, domain);
+ file->file_name = g_path_get_basename (uri);
+ g_free (uri);
+
+ avahi_address_snprint (a, sizeof(a), address);
+
+ method = get_method_for_type (type);
+
+ if (use_dns_sd_uri_for_type (type))
+ {
+ char *encoded_triple;
+ encoded_triple = g_vfs_encode_dns_sd_triple (name, type, domain);
+ file->target_uri = g_strdup_printf ("%s://%s",
+ method,
+ encoded_triple);
+ g_free (encoded_triple);
+ }
+ else
+ {
+ char *path, *user, *user_str;
+ AvahiStringList *path_l, *user_l;
+
+ path = NULL;
+ user_str = NULL;
+ if (txt != NULL)
+ {
+ path_l = avahi_string_list_find (txt, "path");
+ if (path_l != NULL)
+ avahi_string_list_get_pair (path_l, NULL, &path, NULL);
+ user_l = avahi_string_list_find (txt, "u");
+ if (user_l != NULL)
+ {
+ avahi_string_list_get_pair (user_l, NULL, &user, NULL);
+ user_str = g_strconcat (user, "@", NULL);
+ }
+ }
+ if (path == NULL)
+ path = g_strdup ("/");
+
+ if (resolver_supports_mdns)
+ {
+ file->target_uri = g_strdup_printf ("%s://%s%s:%d%s",
+ method,
+ user_str != NULL ? user_str : "",
+ host_name, port, path);
+ }
+ else
+ {
+ if (protocol == AVAHI_PROTO_INET6)
+ {
+ /* an ipv6 address, follow rfc2732 */
+ file->target_uri = g_strdup_printf ("%s://%s[%s]:%d%s",
+ method,
+ user_str?user_str:"",
+ a,
+ port,
+ path);
+ }
+ else
+ {
+ file->target_uri = g_strdup_printf ("%s://%s%s:%d%s",
+ method,
+ user_str?user_str:"",
+ a,
+ port,
+ path);
+ }
+ }
+
+ g_free (user_str);
+ g_free (path);
+ }
+
+ return file;
+}
+
+static void
+link_file_free (LinkFile *file)
+{
+ g_free (file->file_name);
+ g_free (file->name);
+ g_free (file->type);
+ g_free (file->domain);
+ g_free (file->target_uri);
+
+ if (file->icon)
+ g_object_unref (file->icon);
+
+ g_slice_free (LinkFile, file);
+}
+
+static LinkFile *
+lookup_link_file_by_name_and_type (GVfsBackendDnsSd *backend,
+ const char *name,
+ const char *type)
+{
+ GList *l;
+ LinkFile *file;
+
+ for (l = backend->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+ if (strcmp (file->name, name) == 0 &&
+ strcmp (file->type, type) == 0)
+ return file;
+ }
+
+ return NULL;
+}
+
+static LinkFile *
+lookup_link_file (GVfsBackendDnsSd *backend,
+ GVfsJob *job,
+ const char *file_name)
+{
+ GList *l;
+ LinkFile *file;
+
+ if (*file_name != '/')
+ goto out;
+
+ while (*file_name == '/')
+ file_name++;
+
+ if (*file_name == 0)
+ return &root;
+
+ if (strchr (file_name, '/') != NULL)
+ goto out;
+
+ for (l = backend->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+ if (strcmp (file->file_name, file_name) == 0)
+ return file;
+ }
+
+ out:
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+
+ return NULL;
+}
+
+
+static void
+file_info_from_file (LinkFile *file,
+ GFileInfo *info)
+{
+ g_return_if_fail (file != NULL || info != NULL);
+
+ g_file_info_set_name (info, file->file_name);
+ g_file_info_set_display_name (info, file->name);
+
+ if (file->icon)
+ g_file_info_set_icon (info, file->icon);
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT);
+ g_file_info_set_size(info, 0);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, file->target_uri);
+}
+
+/* Backend Functions */
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *file_name,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ LinkFile *file;
+ GList *l;
+ GFileInfo *info;
+
+ file = lookup_link_file (G_VFS_BACKEND_DNS_SD (backend),
+ G_VFS_JOB (job), file_name);
+
+ if (file != &root)
+ {
+ if (file != NULL)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ return TRUE;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB(job));
+
+ /* Enumerate root */
+ for (l = G_VFS_BACKEND_DNS_SD (backend)->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+ info = g_file_info_new ();
+ file_info_from_file (file, info);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ g_vfs_job_enumerate_done (job);
+
+ return TRUE;
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *file_name,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ LinkFile *file;
+
+ file = lookup_link_file (G_VFS_BACKEND_DNS_SD (backend),
+ G_VFS_JOB (job), file_name);
+
+ if (file == &root)
+ {
+ GIcon *icon;
+ char *display_name;
+ char *s;
+
+ s = g_strdup (job->uri);
+ if (s[strlen(s) - 1] == '/') /* job->uri is guranteed to be longer than 1 byte */
+ s[strlen(s) - 1] = '\0';
+ display_name = g_path_get_basename (s);
+ if (strcmp (display_name, "local") == 0)
+ {
+ g_free (display_name);
+ display_name = g_strdup (_("Local Network"));
+ }
+ g_free (s);
+
+ g_file_info_set_name (info, "/");
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_display_name (info, display_name);
+ icon = g_themed_icon_new ("network-workgroup");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_free (display_name);
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_content_type (info, "inode/directory");
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else if (file != NULL)
+ {
+ file_info_from_file (file, info);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+
+static void
+resolve_callback (AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void *userdata)
+{
+ GVfsBackendDnsSd *backend = userdata;
+ LinkFile *file;
+ char *path;
+
+ if (event == AVAHI_RESOLVER_FAILURE)
+ return;
+
+ /* Link-local ipv6 address, can't make a uri from this, ignore */
+ if (address->proto == AVAHI_PROTO_INET6 &&
+ address->data.ipv6.address[0] == 0xfe &&
+ address->data.ipv6.address[1] == 0x80)
+ return;
+
+ file = lookup_link_file_by_name_and_type (backend,
+ name, type);
+
+ if (file != NULL)
+ return;
+
+ file = link_file_new (name, type, domain, host_name, protocol,
+ address, port, txt);
+
+ backend->files = g_list_prepend (backend->files, file);
+
+ path = g_strconcat ("/", file->file_name, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_CREATED,
+ path,
+ NULL);
+ g_free (path);
+}
+
+static void
+browse_callback (AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata)
+{
+ GVfsBackendDnsSd *backend = userdata;
+ AvahiServiceResolver *sr;
+ AvahiClient *client;
+ LinkFile *file;
+ char *path;
+
+ switch (event)
+ {
+ case AVAHI_BROWSER_FAILURE:
+ break;
+
+ case AVAHI_BROWSER_NEW:
+ client = get_global_avahi_client ();
+
+ /* We ignore the returned resolver object. In the callback
+ function we free it. If the server is terminated before
+ the callback function is called the server will free
+ the resolver for us. */
+
+ sr = avahi_service_resolver_new (client, interface, protocol,
+ name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, backend);
+
+ if (sr == NULL)
+ g_warning ("Failed to resolve service name '%s': %s\n", name, avahi_strerror (avahi_client_errno (client)));
+
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ file = lookup_link_file_by_name_and_type (backend,
+ name, type);
+
+ if (file != NULL)
+ {
+ backend->files = g_list_remove (backend->files, file);
+
+ path = g_strconcat ("/", file->file_name, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_DELETED,
+ path,
+ NULL);
+ g_free (path);
+
+ link_file_free (file);
+ }
+
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ break;
+ }
+}
+
+static void
+browse_type (GVfsBackendDnsSd *backend,
+ const char *type)
+{
+ AvahiClient *client;
+ AvahiServiceBrowser *sb;
+ const char *domain;
+
+ client = get_global_avahi_client ();
+
+ domain = NULL;
+ if (strcmp (backend->domain, "local") != 0)
+ domain = backend->domain;
+
+ sb = avahi_service_browser_new (client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ type, domain, 0, browse_callback, backend);
+
+ if (sb == NULL)
+ {
+ g_warning ("Failed to create service browser: %s\n", avahi_strerror( avahi_client_errno (client)));
+ return;
+ }
+
+ backend->browsers = g_list_prepend (backend->browsers, sb);
+
+}
+
+static void
+add_browsers (GVfsBackendDnsSd *backend)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
+ browse_type (backend, dns_sd_types[i].type);
+}
+
+static void
+remove_browsers (GVfsBackendDnsSd *backend)
+{
+ g_list_free (backend->browsers);
+ backend->browsers = NULL;
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendDnsSd *op_backend = G_VFS_BACKEND_DNS_SD (backend);
+ GMountSpec *real_mount_spec;
+ const char *domain;
+
+ domain = g_mount_spec_get (mount_spec, "host");
+
+ if (domain == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "No domain specified for dns-sd share");
+ return TRUE;
+ }
+
+ op_backend->domain = g_strdup (domain);
+
+ if (get_global_avahi_client() == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Unable to initialize avahi");
+ return TRUE;
+ }
+
+ real_mount_spec = g_mount_spec_new ("dns-sd");
+ g_mount_spec_set (real_mount_spec, "host", op_backend->domain);
+ g_vfs_backend_set_mount_spec (backend, real_mount_spec);
+ op_backend->mount_spec = real_mount_spec;
+
+ op_backend->root_monitor = g_vfs_monitor_new (backend);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+/* handles both file and dir monitors,
+ * as we really don't "support" (e.g. fire events for) either, yet. */
+static gboolean
+try_create_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *file_name,
+ GFileMonitorFlags flags)
+{
+ LinkFile *file;
+ GVfsBackendDnsSd *network_backend;
+
+ network_backend = G_VFS_BACKEND_DNS_SD (backend);
+
+ file = lookup_link_file (network_backend, G_VFS_JOB (job), file_name);
+
+ if (file != &root)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't monitor file or directory."));
+ return TRUE;
+ }
+
+ g_vfs_job_create_monitor_set_monitor (job, network_backend->root_monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_dns_sd_init (GVfsBackendDnsSd *network_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (network_backend);
+
+ dnssd_backends = g_list_prepend (dnssd_backends, backend);
+
+ /* TODO: Names, etc */
+ g_vfs_backend_set_display_name (backend, _("Dns-SD"));
+ g_vfs_backend_set_stable_name (backend, _("Network"));
+ g_vfs_backend_set_icon_name (backend, "network-workgroup");
+ g_vfs_backend_set_user_visible (backend, FALSE);
+
+ resolver_supports_mdns = (avahi_nss_support () > 0);
+
+}
+
+static void
+g_vfs_backend_dns_sd_finalize (GObject *object)
+{
+ GVfsBackendDnsSd *backend;
+
+ backend = G_VFS_BACKEND_DNS_SD (object);
+
+ dnssd_backends = g_list_remove (dnssd_backends, backend);
+
+ if (backend->mount_spec)
+ g_mount_spec_unref (backend->mount_spec);
+
+ if (backend->root_monitor)
+ g_object_unref (backend->root_monitor);
+
+ g_free (backend->domain);
+
+ g_list_foreach (backend->files, (GFunc)link_file_free, NULL);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_dns_sd_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_dns_sd_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_dns_sd_class_init (GVfsBackendDnsSdClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_dns_sd_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_create_dir_monitor = try_create_monitor;
+ backend_class->try_create_file_monitor = try_create_monitor;
+}
+
diff --git a/trunk/daemon/gvfsbackenddnssd.h b/trunk/daemon/gvfsbackenddnssd.h
new file mode 100644
index 00000000..8648fc29
--- /dev/null
+++ b/trunk/daemon/gvfsbackenddnssd.h
@@ -0,0 +1,50 @@
+/* gvfs-backend-dns_sd.h - GIO - GLib Input, Output and Streaming Library
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_DNS_SD_H__
+#define __G_VFS_BACKEND_DNS_SD_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_DNS_SD (g_vfs_backend_dns_sd_get_type ())
+#define G_VFS_BACKEND_DNS_SD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSd))
+#define G_VFS_BACKEND_DNS_SD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSdClass))
+#define G_VFS_IS_BACKEND_DNS_SD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_DNS_SD))
+#define G_VFS_IS_BACKEND_DNS_SD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_DNS_SD))
+#define G_VFS_BACKEND_DNS_SD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_DNS_SD, GVfsBackendDnsSdClass))
+
+typedef struct _GVfsBackendDnsSdClass GVfsBackendDnsSdClass;
+
+struct _GVfsBackendDnsSdClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_dns_sd_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_DNS_SD_H__ */
diff --git a/trunk/daemon/gvfsbackendftp.c b/trunk/daemon/gvfsbackendftp.c
new file mode 100644
index 00000000..164a03e5
--- /dev/null
+++ b/trunk/daemon/gvfsbackendftp.c
@@ -0,0 +1,2573 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008,2009 Benjamin Otte <otte@gnome.org>
+ * 2008,2009 Andreas Henriksson <andreas@fatal.se>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Benjamin Otte <otte@gnome.org>
+ * Andreas Henriksson <andreas@fatal.se>
+ */
+
+
+#include <config.h>
+
+#include <errno.h> /* for strerror (EAGAIN) */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <libsoup/soup.h>
+
+#include "gvfsbackendftp.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsdaemonutils.h"
+#include "gvfskeyring.h"
+
+#include "ParseFTPList.h"
+
+#define PRINT_DEBUG
+
+#ifdef PRINT_DEBUG
+#define DEBUG g_print
+#else
+#define DEBUG(...)
+#endif
+
+/* timeout for network connect/send/receive (use 0 for none) */
+#define TIMEOUT_IN_SECONDS 30
+
+/*
+ * about filename interpretation in the ftp backend
+ *
+ * As GVfs composes paths using a slash character, we cannot allow a slash as
+ * part of a basename. Other critical characters are \r \n and sometimes the
+ * space. We therefore g_uri_escape_string() filenames by default and concatenate
+ * paths using slashes. This should make GVfs happy.
+ *
+ * Luckily, TVFS (see RFC 3xxx for details) is a specification that does exactly
+ * what we want. It disallows slashes, \r and \n in filenames, so we can happily
+ * use it without the need to escape. We also can operate on full paths as our
+ * paths exactly match those of a TVFS-using FTP server.
+ */
+
+/* unsinged char is on purpose, so we get warnings when we misuse them */
+typedef unsigned char FtpFile;
+typedef struct _FtpConnection FtpConnection;
+
+typedef struct FtpDirReader FtpDirReader;
+struct FtpDirReader {
+ void (* init_data) (FtpConnection *conn,
+ const FtpFile *dir);
+ GFileInfo * (* get_root) (FtpConnection *conn);
+ gpointer (* iter_new) (FtpConnection *conn);
+ GFileInfo * (* iter_process)(gpointer iter,
+ FtpConnection *conn,
+ const FtpFile *dirname,
+ const FtpFile *must_match_file,
+ const char *line,
+ char **symlink);
+ void (* iter_free) (gpointer iter);
+};
+
+typedef enum {
+ FTP_FEATURE_MDTM = (1 << 0),
+ FTP_FEATURE_SIZE = (1 << 1),
+ FTP_FEATURE_TVFS = (1 << 2),
+ FTP_FEATURE_EPSV = (1 << 3),
+ FTP_FEATURE_UTF8 = (1 << 4),
+} FtpFeatures;
+#define FTP_FEATURES_DEFAULT (FTP_FEATURE_EPSV)
+
+typedef enum {
+ FTP_SYSTEM_UNKNOWN = 0,
+ FTP_SYSTEM_UNIX,
+ FTP_SYSTEM_WINDOWS
+} FtpSystem;
+
+typedef enum {
+ /* Server advertises support for EPSV (or we assume that it supports it),
+ * but it does fail to do so, we set this flag so we can fall back to
+ * PASV. */
+ FTP_WORKAROUND_BROKEN_EPSV = (1 << 0),
+ /* Server replies with a wrong address in PASV, we use connection IP
+ * instead */
+ FTP_WORKAROUND_PASV_ADDR = (1 << 1),
+ /* server does not allow querying features before login, so we try after
+ * logging in instead. */
+ FTP_WORKAROUND_FEAT_AFTER_LOGIN = (1 << 2),
+} FtpWorkarounds;
+
+struct _GVfsBackendFtp
+{
+ GVfsBackend backend;
+
+ SoupAddress * addr;
+ char * user;
+ gboolean has_initial_user;
+ char * password; /* password or NULL for anonymous */
+
+ /* vfuncs */
+ const FtpDirReader * dir_ops;
+
+ /* connection collection */
+ GQueue * queue;
+ GMutex * mutex;
+ GCond * cond;
+ guint connections;
+ guint max_connections;
+
+ /* caching results from dir queries */
+ GStaticRWLock directory_cache_lock;
+ GHashTable * directory_cache;
+};
+
+G_DEFINE_TYPE (GVfsBackendFtp, g_vfs_backend_ftp, G_VFS_TYPE_BACKEND)
+
+#define STATUS_GROUP(status) ((status) / 100)
+
+typedef void (* Ftp550Handler) (FtpConnection *conn, const FtpFile *file);
+
+/*** FTP CONNECTION ***/
+
+struct _FtpConnection
+{
+ /* per-job data */
+ GError * error;
+ GVfsJob * job;
+
+ FtpFeatures features;
+ FtpSystem system;
+ FtpWorkarounds workarounds;
+
+ SoupSocket * commands;
+ gchar * read_buffer;
+ gsize read_buffer_size;
+ gsize read_bytes;
+
+ SoupSocket * data;
+};
+
+static void
+ftp_connection_free (FtpConnection *conn)
+{
+ g_assert (conn->job == NULL);
+
+ if (conn->commands)
+ g_object_unref (conn->commands);
+ if (conn->data)
+ g_object_unref (conn->data);
+
+ g_slice_free (FtpConnection, conn);
+}
+
+#define ftp_connection_in_error(conn) ((conn)->error != NULL)
+#define ftp_connection_clear_error(conn) (g_clear_error (&(conn)->error))
+
+static gboolean
+ftp_connection_pop_job (FtpConnection *conn)
+{
+ gboolean result;
+ GError *error;
+ GVfsJob *job;
+
+ g_return_val_if_fail (conn->job != NULL, FALSE);
+
+ /* sending a reply is racy after the reply is sent. The connection may be
+ * reused in a different thread before the reply sending returns. This is
+ * racy in particular when the connection is used as a read/write handle.
+ */
+ error = conn->error;
+ conn->error = NULL;
+ job = conn->job;
+ conn->job = NULL;
+
+ if (error)
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_clear_error (&error);
+ result = FALSE;
+ }
+ else
+ {
+ g_vfs_job_succeeded (job);
+ result = TRUE;
+ }
+
+ return result;
+}
+
+static void
+ftp_connection_push_job (FtpConnection *conn, GVfsJob *job)
+{
+ g_return_if_fail (conn->job == NULL);
+
+ /* FIXME: ref the job? */
+ conn->job = job;
+}
+
+/**
+ * ftp_error_set_from_response:
+ * @error: pointer to an error to be set or %NULL
+ * @response: an FTP response code to use as the error message
+ *
+ * Sets an error based on an FTP response code.
+ **/
+static void
+ftp_connection_set_error_from_response (FtpConnection *conn, guint response)
+{
+ const char *msg;
+ int code;
+
+ /* Please keep this list ordered by response code,
+ * but group responses with the same message. */
+ switch (response)
+ {
+ case 332: /* Need account for login. */
+ case 532: /* Need account for storing files. */
+ /* FIXME: implement a sane way to handle accounts. */
+ code = G_IO_ERROR_NOT_SUPPORTED;
+ msg = _("Accounts are unsupported");
+ break;
+ case 421: /* Service not available, closing control connection. */
+ code = G_IO_ERROR_FAILED;
+ msg = _("Host closed connection");
+ break;
+ case 425: /* Can't open data connection. */
+ code = G_IO_ERROR_CLOSED;
+ msg = _("Cannot open data connection. Maybe your firewall prevents this?");
+ break;
+ case 426: /* Connection closed; transfer aborted. */
+ code = G_IO_ERROR_CLOSED;
+ msg = _("Data connection closed");
+ break;
+ case 450: /* Requested file action not taken. File unavailable (e.g., file busy). */
+ case 550: /* Requested action not taken. File unavailable (e.g., file not found, no access). */
+ /* FIXME: This is a lot of different errors. So we have to pretend to
+ * be smart here. */
+ code = G_IO_ERROR_FAILED;
+ msg = _("Operation failed");
+ break;
+ case 451: /* Requested action aborted: local error in processing. */
+ code = G_IO_ERROR_FAILED;
+ msg = _("Operation failed");
+ break;
+ case 452: /* Requested action not taken. Insufficient storage space in system. */
+ case 552:
+ code = G_IO_ERROR_NO_SPACE;
+ msg = _("No space left on server");
+ break;
+ case 500: /* Syntax error, command unrecognized. */
+ case 501: /* Syntax error in parameters or arguments. */
+ case 502: /* Command not implemented. */
+ case 503: /* Bad sequence of commands. */
+ case 504: /* Command not implemented for that parameter. */
+ code = G_IO_ERROR_NOT_SUPPORTED;
+ msg = _("Operation unsupported");
+ break;
+ case 530: /* Not logged in. */
+ code = G_IO_ERROR_PERMISSION_DENIED;
+ msg = _("Permission denied");
+ break;
+ case 551: /* Requested action aborted: page type unknown. */
+ code = G_IO_ERROR_FAILED;
+ msg = _("Page type unknown");
+ break;
+ case 553: /* Requested action not taken. File name not allowed. */
+ code = G_IO_ERROR_INVALID_FILENAME;
+ msg = _("Invalid filename");
+ break;
+ default:
+ code = G_IO_ERROR_FAILED;
+ msg = _("Invalid reply");
+ break;
+ }
+
+ DEBUG ("error: %s\n", msg);
+ g_set_error_literal (&conn->error, G_IO_ERROR, code, msg);
+}
+
+/**
+ * ResponseFlags:
+ * RESPONSE_PASS_100: Don't treat 1XX responses, but return them
+ * RESPONSE_PASS_300: Don't treat 3XX responses, but return them
+ * RESPONSE_PASS_400: Don't treat 4XX responses, but return them
+ * RESPONSE_PASS_500: Don't treat 5XX responses, but return them
+ * RESPONSE_PASS_550: Don't treat 550 responses, but return them
+ * RESPONSE_FAIL_200: Fail on a 2XX response
+ */
+
+typedef enum {
+ RESPONSE_PASS_100 = (1 << 0),
+ RESPONSE_PASS_300 = (1 << 1),
+ RESPONSE_PASS_400 = (1 << 2),
+ RESPONSE_PASS_500 = (1 << 3),
+ RESPONSE_PASS_550 = (1 << 4),
+ RESPONSE_FAIL_200 = (1 << 5)
+} ResponseFlags;
+
+/**
+ * ftp_connection_receive:
+ * @conn: connection to receive from
+ * @flags: flags for handling the response
+ * @error: pointer to error message
+ *
+ * Reads a command and stores it in @conn->read_buffer. The read buffer will be
+ * null-terminated and contain @conn->read_bytes bytes. Afterwards, the response
+ * will be parsed and processed according to @flags. By default, all responses
+ * but 2xx will cause an error.
+ *
+ * Returns: 0 on error, the ftp code otherwise
+ **/
+static guint
+ftp_connection_receive (FtpConnection *conn,
+ ResponseFlags flags)
+{
+ SoupSocketIOStatus status;
+ gboolean got_boundary;
+ char *last_line;
+ enum {
+ FIRST_LINE,
+ MULTILINE,
+ DONE
+ } reply_state = FIRST_LINE;
+ guint response = 0;
+
+ g_assert (conn->job != NULL);
+
+ if (ftp_connection_in_error (conn))
+ return 0;
+
+ conn->read_bytes = 0;
+ while (reply_state != DONE)
+ {
+ last_line = conn->read_buffer + conn->read_bytes;
+ do {
+ gsize n_bytes;
+
+ /* the available size must at least allow for boundary size (2)
+ * bytes to be available for reading */
+ if (conn->read_buffer_size - conn->read_bytes < 128)
+ {
+ gsize new_size = conn->read_buffer_size + 1024;
+ /* FIXME: upper limit for size? */
+ gchar *new = g_try_realloc (conn->read_buffer, new_size);
+ if (new)
+ {
+ /* make last line relative to new allocation */
+ last_line = new + (last_line - conn->read_buffer);
+ conn->read_buffer = new;
+ conn->read_buffer_size = new_size;
+ }
+ else
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply"));
+ return 0;
+ }
+ }
+ status = soup_socket_read_until (conn->commands,
+ conn->read_buffer + conn->read_bytes,
+ /* -1 byte for nul-termination */
+ conn->read_buffer_size - conn->read_bytes - 1,
+ "\r\n",
+ 2,
+ &n_bytes,
+ &got_boundary,
+ conn->job->cancellable,
+ &conn->error);
+
+ conn->read_bytes += n_bytes;
+ conn->read_buffer[conn->read_bytes] = 0;
+
+ g_assert (status != SOUP_SOCKET_WOULD_BLOCK);
+ if (status == SOUP_SOCKET_ERROR)
+ return 0;
+
+ if (n_bytes == 0)
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply"));
+ return 0;
+ }
+ } while (!got_boundary);
+
+ DEBUG ("<-- %s", last_line);
+
+ if (reply_state == FIRST_LINE)
+ {
+ if (last_line[0] <= '0' || last_line[0] > '5' ||
+ last_line[1] < '0' || last_line[1] > '9' ||
+ last_line[2] < '0' || last_line[2] > '9')
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply"));
+ return 0;
+ }
+ response = 100 * (last_line[0] - '0') +
+ 10 * (last_line[1] - '0') +
+ (last_line[2] - '0');
+ if (last_line[3] == ' ')
+ reply_state = DONE;
+ else if (last_line[3] == '-')
+ reply_state = MULTILINE;
+ else
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply"));
+ return 0;
+ }
+ }
+ else
+ {
+ if (last_line[0] == conn->read_buffer[0] &&
+ last_line[1] == conn->read_buffer[1] &&
+ last_line[2] == conn->read_buffer[2] &&
+ last_line[3] == ' ')
+ reply_state = DONE;
+ }
+ }
+
+ switch (STATUS_GROUP (response))
+ {
+ case 0:
+ return 0;
+ case 1:
+ if (flags & RESPONSE_PASS_100)
+ break;
+ ftp_connection_set_error_from_response (conn, response);
+ return 0;
+ case 2:
+ if (flags & RESPONSE_FAIL_200)
+ {
+ ftp_connection_set_error_from_response (conn, response);
+ return 0;
+ }
+ break;
+ case 3:
+ if (flags & RESPONSE_PASS_300)
+ break;
+ ftp_connection_set_error_from_response (conn, response);
+ return 0;
+ case 4:
+ if (flags & RESPONSE_PASS_400)
+ break;
+ ftp_connection_set_error_from_response (conn, response);
+ return 0;
+ break;
+ case 5:
+ if ((flags & RESPONSE_PASS_500) || (response == 550 && (flags & RESPONSE_PASS_550)))
+ break;
+ ftp_connection_set_error_from_response (conn, response);
+ return 0;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return response;
+}
+
+/**
+ * ftp_connection_send:
+ * @conn: the connection to send to
+ * @flags: #ResponseFlags to use
+ * @error: pointer to take an error
+ * @format: format string to construct command from
+ * (without trailing \r\n)
+ * @...: arguments to format string
+ *
+ * Takes a command, waits for an answer and parses it. Without any @flags, FTP
+ * codes other than 2xx cause an error. The last read ftp command will be put
+ * into @conn->read_buffer.
+ *
+ * Returns: 0 on error or the receied FTP code otherwise.
+ *
+ **/
+static guint
+ftp_connection_sendv (FtpConnection *conn,
+ ResponseFlags flags,
+ const char * format,
+ va_list varargs)
+{
+ GString *command;
+ SoupSocketIOStatus status;
+ gsize n_bytes;
+ guint response;
+
+ g_assert (conn->job != NULL);
+
+ if (ftp_connection_in_error (conn))
+ return 0;
+
+ command = g_string_new ("");
+ g_string_append_vprintf (command, format, varargs);
+#ifdef PRINT_DEBUG
+ if (g_str_has_prefix (command->str, "PASS"))
+ DEBUG ("--> PASS ***\n");
+ else
+ DEBUG ("--> %s\n", command->str);
+#endif
+ g_string_append (command, "\r\n");
+ status = soup_socket_write (conn->commands,
+ command->str,
+ command->len,
+ &n_bytes,
+ conn->job->cancellable,
+ &conn->error);
+ switch (status)
+ {
+ case SOUP_SOCKET_OK:
+ case SOUP_SOCKET_EOF:
+ if (n_bytes == command->len)
+ break;
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("broken transmission"));
+ /* fall through */
+ case SOUP_SOCKET_ERROR:
+ g_string_free (command, TRUE);
+ return 0;
+ case SOUP_SOCKET_WOULD_BLOCK:
+ default:
+ g_assert_not_reached ();
+ }
+ g_string_free (command, TRUE);
+
+ response = ftp_connection_receive (conn, flags);
+ return response;
+}
+
+static guint
+ftp_connection_send (FtpConnection *conn,
+ ResponseFlags flags,
+ const char * format,
+ ...) G_GNUC_PRINTF (3, 4);
+static guint
+ftp_connection_send (FtpConnection *conn,
+ ResponseFlags flags,
+ const char * format,
+ ...)
+{
+ va_list varargs;
+ guint response;
+
+ va_start (varargs, format);
+ response = ftp_connection_sendv (conn,
+ flags,
+ format,
+ varargs);
+ va_end (varargs);
+ return response;
+}
+
+static void
+ftp_connection_check_file (FtpConnection *conn,
+ const Ftp550Handler *handlers,
+ const FtpFile *file)
+{
+ while (*handlers && !ftp_connection_in_error (conn))
+ {
+ (*handlers) (conn, file);
+ handlers++;
+ }
+}
+
+static guint
+ftp_connection_send_and_check (FtpConnection *conn,
+ ResponseFlags flags,
+ const Ftp550Handler *handlers,
+ const FtpFile *file,
+ const char *format,
+ ...) G_GNUC_PRINTF (5, 6);
+static guint
+ftp_connection_send_and_check (FtpConnection *conn,
+ ResponseFlags flags,
+ const Ftp550Handler *handlers,
+ const FtpFile *file,
+ const char *format,
+ ...)
+{
+ va_list varargs;
+ guint response;
+
+ /* check that there's no 550 handling used - don't allow bad use of API */
+ g_return_val_if_fail ((flags & RESPONSE_PASS_550) == 0, 0);
+ g_return_val_if_fail (handlers != NULL, 0);
+ g_return_val_if_fail (file != NULL, 0);
+
+ va_start (varargs, format);
+ response = ftp_connection_sendv (conn,
+ flags | RESPONSE_PASS_550,
+ format,
+ varargs);
+ va_end (varargs);
+ if (response == 550)
+ {
+ ftp_connection_check_file (conn, handlers, file);
+ if (!ftp_connection_in_error (conn))
+ ftp_connection_set_error_from_response (conn, response);
+ response = 0;
+ }
+ return response;
+}
+
+static void
+ftp_connection_parse_features (FtpConnection *conn)
+{
+ struct {
+ const char * name; /* name of feature */
+ FtpFeatures enable; /* flags to enable with this feature */
+ } features[] = {
+ { "MDTM", FTP_FEATURE_MDTM },
+ { "SIZE", FTP_FEATURE_SIZE },
+ { "TVFS", FTP_FEATURE_TVFS },
+ { "EPSV", FTP_FEATURE_EPSV },
+ { "UTF8", FTP_FEATURE_UTF8 },
+ };
+ char **supported;
+ guint i, j;
+
+ /* The "\n" should really be "\r\n" but we deal with both to handle broken
+ * servers. We strip off '\r' later, if it exists. */
+ supported = g_strsplit (conn->read_buffer, "\n", -1);
+
+ for (i = 1; supported[i]; i++)
+ {
+ char *feature = supported[i];
+ int len;
+
+ if (feature[0] != ' ')
+ continue;
+ feature++;
+
+ /* There should just be one space according to RFC2389, but some
+ * servers have more so we deal with any number of leading spaces.
+ */
+ while (g_ascii_isspace (feature[0]))
+ feature++;
+
+ /* strip off trailing '\r', if it exists. */
+ len = strlen(feature);
+ if (len > 0 && feature[len-1] == '\r')
+ feature[len-1] = '\0';
+
+ for (j = 0; j < G_N_ELEMENTS (features); j++)
+ {
+ if (g_ascii_strcasecmp (feature, features[j].name) == 0)
+ {
+ DEBUG ("feature %s supported\n", features[j].name);
+ conn->features |= features[j].enable;
+ }
+ }
+ }
+
+ g_strfreev (supported);
+}
+
+/* NB: you must free the connection if it's in error returning from here */
+static FtpConnection *
+ftp_connection_create (SoupAddress * addr,
+ GVfsJob * job)
+{
+ FtpConnection *conn;
+ guint status;
+
+ conn = g_slice_new0 (FtpConnection);
+ ftp_connection_push_job (conn, job);
+
+ conn->commands = soup_socket_new ("non-blocking", FALSE,
+ "remote-address", addr,
+ "timeout", TIMEOUT_IN_SECONDS,
+ NULL);
+ status = soup_socket_connect_sync (conn->commands, job->cancellable);
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
+ {
+ /* FIXME: better error messages depending on status please */
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_HOST_NOT_FOUND,
+ _("Could not connect to host"));
+ }
+
+ ftp_connection_receive (conn, 0);
+ return conn;
+}
+
+static guint
+ftp_connection_login (FtpConnection *conn,
+ const char * username,
+ const char * password)
+{
+ guint status;
+
+ if (ftp_connection_in_error (conn))
+ return 0;
+
+ status = ftp_connection_send (conn, RESPONSE_PASS_300,
+ "USER %s", username);
+
+ if (STATUS_GROUP (status) == 3)
+ {
+ /* rationale for choosing the default password:
+ * - some ftp servers expect something that looks like an email address
+ * - we don't want to send the user's name or address, as that would be
+ * a privacy problem
+ * - we want to give ftp server administrators a chance to notify us of
+ * problems with our client.
+ * - we don't want to drown in spam.
+ */
+ if (password == NULL || password[0] == 0)
+ password = "gvfsd-ftp-" VERSION "@example.com";
+ status = ftp_connection_send (conn, 0,
+ "PASS %s", password);
+ }
+
+ return status;
+}
+
+static void
+ftp_connection_parse_system (FtpConnection *conn)
+{
+ static const struct {
+ const char *id;
+ FtpSystem system;
+ } known_systems[] = {
+ /* NB: the first entry that matches is taken, so order matters */
+ { "UNIX ", FTP_SYSTEM_UNIX },
+ { "WINDOWS_NT ", FTP_SYSTEM_WINDOWS }
+ };
+ guint i;
+ char *system_name = conn->read_buffer + 4;
+
+ for (i = 0; i < G_N_ELEMENTS (known_systems); i++)
+ {
+ if (g_ascii_strncasecmp (system_name,
+ known_systems[i].id,
+ strlen (known_systems[i].id)) == 0)
+ {
+ conn->system = known_systems[i].system;
+ DEBUG ("system is %u\n", conn->system);
+ break;
+ }
+ }
+}
+
+static void
+ftp_connection_prepare (FtpConnection *conn)
+{
+ /* check supported features */
+ if (ftp_connection_send (conn, 0, "FEAT") != 0) {
+ ftp_connection_parse_features (conn);
+ } else {
+ ftp_connection_clear_error(conn);
+ conn->workarounds |= FTP_WORKAROUND_FEAT_AFTER_LOGIN;
+ conn->features = 0;
+ }
+
+ /* instruct server that we'll give and assume we get utf8 */
+ if (conn->features & FTP_FEATURE_UTF8)
+ ftp_connection_send (conn, 0, "OPTS UTF8 ON");
+}
+
+static gboolean
+ftp_connection_use (FtpConnection *conn)
+{
+ /* only binary transfers please */
+ ftp_connection_send (conn, 0, "TYPE I");
+ if (ftp_connection_in_error (conn))
+ return FALSE;
+
+#if 0
+ /* RFC 2428 suggests to send this to make NAT routers happy */
+ /* XXX: Disabled for the following reasons:
+ * - most ftp clients don't use it
+ * - lots of broken ftp servers can't see the difference between
+ * "EPSV" and "EPSV ALL"
+ * - impossible to dynamically fall back to regular PASV in case
+ * EPSV doesn't work for some reason.
+ * If this makes your ftp connection fail, please file a bug and we will
+ * try to invent a way to make this all work. Until then, we'll just
+ * ignore the RFC.
+ */
+ if (conn->features & FTP_FEATURE_EPSV)
+ ftp_connection_send (conn, 0, "EPSV ALL");
+ ftp_connection_clear_error(conn);
+#endif
+
+ if (conn->workarounds & FTP_WORKAROUND_FEAT_AFTER_LOGIN) {
+ if (ftp_connection_send (conn, 0, "FEAT") != 0) {
+ ftp_connection_parse_features (conn);
+ } else {
+ ftp_connection_clear_error(conn);
+ conn->features = FTP_FEATURE_EPSV;
+ }
+ }
+
+ if (ftp_connection_send (conn, 0, "SYST"))
+ ftp_connection_parse_system (conn);
+ ftp_connection_clear_error(conn);
+
+ return TRUE;
+}
+
+static gboolean
+ftp_connection_open_data_connection (FtpConnection *conn, SoupAddress *addr)
+{
+ guint status;
+
+ conn->data = soup_socket_new ("non-blocking", FALSE,
+ "remote-address", addr,
+ "timeout", TIMEOUT_IN_SECONDS,
+ NULL);
+ g_object_unref (addr);
+ status = soup_socket_connect_sync (conn->data, conn->job->cancellable);
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
+ {
+ /* FIXME: better error messages depending on status please */
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_HOST_NOT_FOUND,
+ _("Could not connect to host"));
+ g_object_unref (conn->data);
+ conn->data = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+ftp_connection_ensure_data_connection_epsv (FtpConnection *conn)
+{
+ const char *s;
+ guint port;
+ SoupAddress *addr;
+ guint status;
+ gboolean connected;
+
+ if ((conn->features & FTP_FEATURE_EPSV) == 0)
+ return FALSE;
+
+ if (conn->workarounds & FTP_WORKAROUND_BROKEN_EPSV)
+ return FALSE;
+
+ status = ftp_connection_send (conn, RESPONSE_PASS_500, "EPSV");
+ if (STATUS_GROUP (status) != 2)
+ return FALSE;
+
+ s = strrchr (conn->read_buffer, '(');
+ if (!s)
+ return FALSE;
+
+ s += 4;
+ port = strtoul (s, NULL, 10);
+ if (port == 0)
+ return FALSE;
+
+ addr = soup_address_new (
+ soup_address_get_name (soup_socket_get_remote_address (conn->commands)),
+ port);
+
+ connected = ftp_connection_open_data_connection (conn, addr);
+ if (!connected)
+ {
+ DEBUG ("Successful EPSV response code, but data connection failed. Enabling FTP_WORKAROUND_BROKEN_EPSV.\n");
+ conn->workarounds |= FTP_WORKAROUND_BROKEN_EPSV;
+ ftp_connection_clear_error (conn);
+ }
+ return connected;
+}
+
+static gboolean
+ftp_connection_ensure_data_connection_pasv (FtpConnection *conn)
+{
+ guint ip1, ip2, ip3, ip4, port1, port2;
+ const char *s;
+ SoupAddress *addr;
+ guint status;
+
+ /* only binary transfers please */
+ status = ftp_connection_send (conn, 0, "PASV");
+ if (status == 0)
+ return FALSE;
+
+ /* parse response and try to find the address to connect to.
+ * This code does the same as curl.
+ */
+ for (s = conn->read_buffer; *s; s++)
+ {
+ if (sscanf (s, "%u,%u,%u,%u,%u,%u",
+ &ip1, &ip2, &ip3, &ip4,
+ &port1, &port2) == 6)
+ break;
+ }
+ if (*s == 0)
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply"));
+ return FALSE;
+ }
+
+ if (!(conn->workarounds & FTP_WORKAROUND_PASV_ADDR))
+ {
+ char *ip;
+
+ ip = g_strdup_printf ("%u.%u.%u.%u", ip1, ip2, ip3, ip4);
+ addr = soup_address_new (ip, port1 << 8 | port2);
+ g_free (ip);
+
+ if (ftp_connection_open_data_connection (conn, addr))
+ return TRUE;
+
+ /* set workaround flag (see below), so we don't try this again */
+ DEBUG ("Successfull PASV response but data connection failed. Enabling FTP_WORKAROUND_PASV_ADDR.\n");
+ conn->workarounds |= FTP_WORKAROUND_PASV_ADDR;
+ ftp_connection_clear_error (conn);
+ }
+
+ /* Workaround code:
+ * Various ftp servers aren;t setup correctly when behind a NAT. They report
+ * their own IP address (like 10.0.0.4) and not the address in front of the
+ * NAT. But this is likely the same address that we connected to with our
+ * command connetion. So if the address given by PASV fails, we fall back
+ * to the address of the command stream.
+ */
+ addr = soup_address_new (soup_address_get_name (soup_socket_get_remote_address (conn->commands)),
+ port1 << 8 | port2);
+ return ftp_connection_open_data_connection (conn, addr);
+}
+
+static gboolean
+ftp_connection_ensure_data_connection (FtpConnection *conn)
+{
+ if (ftp_connection_ensure_data_connection_epsv (conn))
+ return TRUE;
+
+ if (ftp_connection_in_error (conn))
+ return FALSE;
+
+ if (ftp_connection_ensure_data_connection_pasv (conn))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+ftp_connection_close_data_connection (FtpConnection *conn)
+{
+ if (conn == NULL || conn->data == NULL)
+ return;
+
+ g_object_unref (conn->data);
+ conn->data = NULL;
+}
+
+/*** FILE MAPPINGS ***/
+
+/* FIXME: This most likely needs adaption to non-unix like directory structures.
+ * There's at least the case of multiple roots (Netware) plus probably a shitload
+ * of weird old file systems (starting with MS-DOS)
+ * But we first need a way to detect that.
+ */
+
+/**
+ * FtpFile:
+ *
+ * Byte string used to identify a file on the FTP server. It's typedef'ed to
+ * make it easy to distinguish from GVfs paths.
+ */
+
+static FtpFile *
+ftp_filename_from_gvfs_path (FtpConnection *conn, const char *pathname)
+{
+ return (FtpFile *) g_strdup (pathname);
+}
+
+static char *
+ftp_filename_to_gvfs_path (FtpConnection *conn, const FtpFile *filename)
+{
+ return g_strdup ((const char *) filename);
+}
+
+/* Takes an FTP dirname and a basename (as used in RNTO or as result from LIST
+ * or similar) and gets the new ftp filename from it.
+ *
+ * Returns: the filename or %NULL if filename construction wasn't possible.
+ */
+/* let's hope we can live without a connection here, or we have to rewrite LIST */
+static FtpFile *
+ftp_filename_construct (FtpConnection *conn, const FtpFile *dirname, const char *basename)
+{
+ if (strpbrk (basename, "/\r\n"))
+ return NULL;
+
+ return (FtpFile *) g_build_path ("/", (char *) dirname, basename, NULL);
+}
+
+#define ftp_filename_equal g_str_equal
+
+/*** COMMON FUNCTIONS WITH SPECIAL HANDLING ***/
+
+static gboolean
+ftp_connection_cd (FtpConnection *conn, const FtpFile *file)
+{
+ guint response = ftp_connection_send (conn,
+ RESPONSE_PASS_500,
+ "CWD %s", file);
+ if (response == 550)
+ {
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ response = 0;
+ }
+ else if (STATUS_GROUP (response) == 5)
+ {
+ ftp_connection_set_error_from_response (conn, response);
+ response = 0;
+ }
+
+ return response != 0;
+}
+
+static gboolean
+ftp_connection_try_cd (FtpConnection *conn, const FtpFile *file)
+{
+ if (ftp_connection_in_error (conn))
+ return FALSE;
+
+ if (!ftp_connection_cd (conn, file))
+ {
+ ftp_connection_clear_error (conn);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*** default directory reading ***/
+
+static void
+dir_default_init_data (FtpConnection *conn, const FtpFile *dir)
+{
+ ftp_connection_cd (conn, dir);
+ ftp_connection_ensure_data_connection (conn);
+
+ ftp_connection_send (conn,
+ RESPONSE_PASS_100 | RESPONSE_FAIL_200,
+ (conn->system == FTP_SYSTEM_UNIX) ? "LIST -a" : "LIST");
+}
+
+static GFileInfo *
+dir_default_get_root (FtpConnection *conn)
+{
+ GFileInfo *info;
+ GIcon *icon;
+ char *display_name;
+
+ info = g_file_info_new ();
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+
+ g_file_info_set_name (info, "/");
+ display_name = g_strdup_printf (_("/ on %s"),
+ soup_address_get_name (soup_socket_get_remote_address (conn->commands)));
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ g_file_info_set_edit_name (info, "/");
+
+ g_file_info_set_content_type (info, "inode/directory");
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, "inode/directory");
+
+ icon = g_themed_icon_new ("folder-remote");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+
+ return info;
+}
+
+static gpointer
+dir_default_iter_new (FtpConnection *conn)
+{
+ return g_slice_new0 (struct list_state);
+}
+
+static GFileInfo *
+dir_default_iter_process (gpointer iter,
+ FtpConnection *conn,
+ const FtpFile *dirname,
+ const FtpFile *must_match_file,
+ const char *line,
+ char **symlink)
+{
+ struct list_state *state = iter;
+ struct list_result result = { 0, };
+ GTimeVal tv = { 0, 0 };
+ GFileInfo *info;
+ int type;
+ FtpFile *name;
+ char *s, *t;
+
+ type = ParseFTPList (line, state, &result);
+ if (type != 'd' && type != 'f' && type != 'l')
+ return NULL;
+
+ /* don't list . and .. directories
+ * Let's hope they're not important files on some ftp servers
+ */
+ if (type == 'd')
+ {
+ if (result.fe_fnlen == 1 &&
+ result.fe_fname[0] == '.')
+ return NULL;
+ if (result.fe_fnlen == 2 &&
+ result.fe_fname[0] == '.' &&
+ result.fe_fname[1] == '.')
+ return NULL;
+ }
+
+ s = g_strndup (result.fe_fname, result.fe_fnlen);
+ if (dirname)
+ {
+ name = ftp_filename_construct (conn, dirname, s);
+ g_free (s);
+ }
+ else
+ name = (FtpFile *) s;
+ if (name == NULL)
+ return NULL;
+
+ if (must_match_file && !ftp_filename_equal (name, must_match_file))
+ {
+ g_free (name);
+ return NULL;
+ }
+
+ info = g_file_info_new ();
+
+ s = ftp_filename_to_gvfs_path (conn, name);
+
+ t = g_path_get_basename (s);
+ g_file_info_set_name (info, t);
+ g_free (t);
+
+ if (type == 'l')
+ {
+ char *link;
+
+ link = g_strndup (result.fe_lname, result.fe_lnlen);
+
+ /* FIXME: this whole stuff is not FtpFile save */
+ g_file_info_set_symlink_target (info, link);
+ g_file_info_set_is_symlink (info, TRUE);
+
+ if (symlink)
+ {
+ char *str = g_path_get_dirname (s);
+ char *symlink_file = g_build_path ("/", str, link, NULL);
+
+ g_free (str);
+ while ((str = strstr (symlink_file, "/../")))
+ {
+ char *end = str + 4;
+ char *start;
+ start = str - 1;
+ while (start >= symlink_file && *start != '/')
+ start--;
+
+ if (start < symlink_file) {
+ *symlink_file = '/';
+ start = symlink_file;
+ }
+
+ memmove (start + 1, end, strlen (end) + 1);
+ }
+ str = symlink_file + strlen (symlink_file) - 1;
+ while (*str == '/' && str > symlink_file)
+ *str-- = 0;
+ *symlink = symlink_file;
+ }
+ g_free (link);
+ }
+ else if (symlink)
+ *symlink = NULL;
+
+ g_file_info_set_size (info, strtoul (result.fe_size, NULL, 10));
+
+ gvfs_file_info_populate_default (info, s,
+ type == 'f' ? G_FILE_TYPE_REGULAR :
+ type == 'l' ? G_FILE_TYPE_SYMBOLIC_LINK :
+ G_FILE_TYPE_DIRECTORY);
+
+ if (conn->system == FTP_SYSTEM_UNIX)
+ g_file_info_set_is_hidden (info, result.fe_fnlen > 0 &&
+ result.fe_fname[0] == '.');
+
+ g_free (s);
+ g_free (name);
+
+ /* Workaround:
+ * result.fetime.tm_year contains actual year instead of offset-from-1900,
+ * which mktime expects.
+ */
+ if (result.fe_time.tm_year >= 1900)
+ result.fe_time.tm_year -= 1900;
+
+ tv.tv_sec = mktime (&result.fe_time);
+ if (tv.tv_sec != -1)
+ g_file_info_set_modification_time (info, &tv);
+
+ return info;
+}
+
+static void
+dir_default_iter_free (gpointer iter)
+{
+ g_slice_free (struct list_state, iter);
+}
+
+static const FtpDirReader dir_default = {
+ dir_default_init_data,
+ dir_default_get_root,
+ dir_default_iter_new,
+ dir_default_iter_process,
+ dir_default_iter_free
+};
+
+/*** BACKEND ***/
+
+static void
+g_vfs_backend_ftp_push_connection (GVfsBackendFtp *ftp, FtpConnection *conn)
+{
+ /* we allow conn == NULL to ease error cases */
+ if (conn == NULL)
+ return;
+
+ if (conn->job)
+ ftp_connection_pop_job (conn);
+
+ g_mutex_lock (ftp->mutex);
+ if (ftp->queue)
+ {
+ g_queue_push_tail (ftp->queue, conn);
+ g_cond_signal (ftp->cond);
+ }
+ else
+ ftp_connection_free (conn);
+ g_mutex_unlock (ftp->mutex);
+}
+
+static void
+do_broadcast (GCancellable *cancellable, GCond *cond)
+{
+ g_cond_broadcast (cond);
+}
+
+static FtpConnection *
+g_vfs_backend_ftp_pop_connection (GVfsBackendFtp *ftp,
+ GVfsJob * job)
+{
+ FtpConnection *conn = NULL;
+ GTimeVal now;
+ guint id;
+
+ g_mutex_lock (ftp->mutex);
+ id = g_signal_connect (job->cancellable,
+ "cancelled",
+ G_CALLBACK (do_broadcast),
+ ftp->cond);
+ while (conn == NULL && ftp->queue != NULL)
+ {
+ if (g_cancellable_is_cancelled (job->cancellable))
+ break;
+ conn = g_queue_pop_head (ftp->queue);
+
+ if (conn != NULL)
+ {
+ /* Figure out if this connection had a timeout sent. If so, skip it. */
+ g_mutex_unlock (ftp->mutex);
+ ftp_connection_push_job (conn, job);
+ if (ftp_connection_send (conn, 0, "NOOP"))
+ break;
+
+ ftp_connection_clear_error (conn);
+ conn->job = NULL;
+ ftp_connection_free (conn);
+ conn = NULL;
+ g_mutex_lock (ftp->mutex);
+ ftp->connections--;
+ continue;
+ }
+
+ if (ftp->connections < ftp->max_connections)
+ {
+ /* Save current number of connections here, so we can limit maximum
+ * connections later.
+ * This is necessary for threading reasons (connections can be
+ * opened or closed while we are still in the opening process. */
+ guint maybe_max_connections = ftp->connections;
+
+ ftp->connections++;
+ g_mutex_unlock (ftp->mutex);
+ conn = ftp_connection_create (ftp->addr, job);
+ ftp_connection_prepare (conn);
+ ftp_connection_login (conn, ftp->user, ftp->password);
+ ftp_connection_use (conn);
+ if (G_LIKELY (!ftp_connection_in_error (conn)))
+ break;
+
+ ftp_connection_clear_error (conn);
+ /* Don't call ftp_connection_pop_job () here, the job isn't done yet */
+ conn->job = NULL;
+ ftp_connection_free (conn);
+ conn = NULL;
+ g_mutex_lock (ftp->mutex);
+ ftp->connections--;
+ ftp->max_connections = MIN (ftp->max_connections, maybe_max_connections);
+ if (ftp->max_connections == 0)
+ {
+ DEBUG ("no more connections left, exiting...");
+ /* FIXME: shut down properly */
+ exit (0);
+ }
+
+ continue;
+ }
+
+ g_get_current_time (&now);
+ g_time_val_add (&now, TIMEOUT_IN_SECONDS * 1000 * 1000);
+ if (!g_cond_timed_wait (ftp->cond, ftp->mutex, &now))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ /* defeat string freeze! */
+ /* _("Resource temporarily unavailable")); */
+ "%s", g_strerror (EAGAIN));
+ break;
+ }
+ }
+ g_signal_handler_disconnect (job->cancellable, id);
+
+ return conn;
+}
+
+static void
+g_vfs_backend_ftp_finalize (GObject *object)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (object);
+
+ if (ftp->addr)
+ g_object_unref (ftp->addr);
+
+ /* has been cleared on unmount */
+ g_assert (ftp->queue == NULL);
+ g_cond_free (ftp->cond);
+ g_mutex_free (ftp->mutex);
+
+ g_hash_table_destroy (ftp->directory_cache);
+ g_static_rw_lock_free (&ftp->directory_cache_lock);
+
+ g_free (ftp->user);
+ g_free (ftp->password);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_ftp_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_ftp_parent_class)->finalize) (object);
+}
+
+static void
+list_free (gpointer list)
+{
+ g_list_foreach (list, (GFunc) g_free, NULL);
+ g_list_free (list);
+}
+
+static void
+g_vfs_backend_ftp_init (GVfsBackendFtp *ftp)
+{
+ ftp->mutex = g_mutex_new ();
+ ftp->cond = g_cond_new ();
+
+ ftp->directory_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ list_free);
+ g_static_rw_lock_init (&ftp->directory_cache_lock);
+
+ ftp->dir_ops = &dir_default;
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ char *host;
+ char *prompt = NULL;
+ char *username;
+ char *password;
+ char *display_name;
+ gboolean aborted, anonymous, break_on_fail;
+ GPasswordSave password_save = G_PASSWORD_SAVE_NEVER;
+ guint port;
+
+ conn = ftp_connection_create (ftp->addr,
+ G_VFS_JOB (job));
+ /* fail fast here. No need to ask for a password if we know the hostname
+ * doesn't exist or the given host/port doesn't have an ftp server running.
+ */
+ if (ftp_connection_in_error (conn))
+ {
+ ftp_connection_pop_job (conn);
+ ftp_connection_free (conn);
+ return;
+ }
+
+ ftp_connection_prepare (conn);
+
+ port = soup_address_get_port (ftp->addr);
+ /* FIXME: need to translate this? */
+ if (port == 21)
+ host = g_strdup (soup_address_get_name (ftp->addr));
+ else
+ host = g_strdup_printf ("%s:%u",
+ soup_address_get_name (ftp->addr),
+ port);
+
+ username = NULL;
+ password = NULL;
+ break_on_fail = FALSE;
+
+ if (ftp->user != NULL && strcmp (ftp->user, "anonymous") == 0)
+ {
+ anonymous = TRUE;
+ break_on_fail = TRUE;
+ goto try_login;
+ }
+
+ if (g_vfs_keyring_lookup_password (ftp->user,
+ soup_address_get_name (ftp->addr),
+ NULL,
+ "ftp",
+ NULL,
+ NULL,
+ port == 21 ? 0 : port,
+ &username,
+ NULL,
+ &password))
+ {
+ anonymous = FALSE;
+ goto try_login;
+ }
+
+ while (TRUE)
+ {
+ GAskPasswordFlags flags;
+ if (prompt == NULL)
+ {
+ if (ftp->has_initial_user)
+ /* Translators: the first %s is the username, the second the host name */
+ prompt = g_strdup_printf (_("Enter password for ftp as %s on %s"), ftp->user, host);
+ else
+ /* translators: %s here is the hostname */
+ prompt = g_strdup_printf (_("Enter password for ftp on %s"), host);
+ }
+
+ flags = G_ASK_PASSWORD_NEED_PASSWORD;
+
+ if (!ftp->has_initial_user)
+ flags |= G_ASK_PASSWORD_NEED_USERNAME | G_ASK_PASSWORD_ANONYMOUS_SUPPORTED;
+
+ if (g_vfs_keyring_is_available ())
+ flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+
+ if (!g_mount_source_ask_password (
+ mount_source,
+ prompt,
+ ftp->user,
+ NULL,
+ flags,
+ &aborted,
+ &password,
+ &username,
+ NULL,
+ &anonymous,
+ &password_save) ||
+ aborted)
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Password dialog cancelled"));
+ break;
+ }
+
+ /* NEED_USERNAME wasn't set */
+ if (ftp->has_initial_user)
+ {
+ g_free (username);
+ username = g_strdup (ftp->user);
+ }
+
+try_login:
+ g_free (ftp->user);
+ g_free (ftp->password);
+ if (anonymous)
+ {
+ if (ftp_connection_login (conn, "anonymous", "") != 0)
+ {
+ ftp->user = g_strdup ("anonymous");
+ ftp->password = g_strdup ("");
+ break;
+ }
+ ftp->user = NULL;
+ ftp->password = NULL;
+ }
+ else
+ {
+ ftp->user = username ? g_strdup (username) : g_strdup ("");
+ ftp->password = g_strdup (password);
+ if (ftp_connection_login (conn, username, password) != 0)
+ break;
+ }
+ g_free (username);
+ g_free (password);
+
+ if (break_on_fail ||
+ !g_error_matches (conn->error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
+ break;
+
+ ftp_connection_clear_error (conn);
+ }
+
+ ftp_connection_use (conn);
+
+ if (ftp_connection_in_error (conn))
+ {
+ ftp_connection_pop_job (conn);
+ ftp_connection_free (conn);
+ }
+ else
+ {
+ if (prompt && !anonymous)
+ {
+ /* a prompt was created, so we have to save the password */
+ g_vfs_keyring_save_password (ftp->user,
+ soup_address_get_name (ftp->addr),
+ NULL,
+ "ftp",
+ NULL,
+ NULL,
+ port == 21 ? 0 : port,
+ ftp->password,
+ password_save);
+ g_free (prompt);
+ }
+
+ mount_spec = g_mount_spec_new ("ftp");
+ g_mount_spec_set (mount_spec, "host", soup_address_get_name (ftp->addr));
+ if (port != 21)
+ {
+ char *port_str = g_strdup_printf ("%u", port);
+ g_mount_spec_set (mount_spec, "port", port_str);
+ g_free (port_str);
+ }
+
+ if (ftp->has_initial_user)
+ g_mount_spec_set (mount_spec, "user", ftp->user);
+
+ if (g_str_equal (ftp->user, "anonymous"))
+ display_name = g_strdup_printf (_("ftp on %s"), host);
+ else
+ {
+ /* Translators: the first %s is the username, the second the host name */
+ display_name = g_strdup_printf (_("ftp as %s on %s"), ftp->user, host);
+ }
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+ g_vfs_backend_set_icon_name (backend, "folder-remote");
+
+ ftp->connections = 1;
+ ftp->max_connections = G_MAXUINT;
+ ftp->queue = g_queue_new ();
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+ }
+
+ g_free (host);
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ const char *host, *port_str;
+ guint port;
+
+ host = g_mount_spec_get (mount_spec, "host");
+ if (host == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("No hostname specified"));
+ return TRUE;
+ }
+ port_str = g_mount_spec_get (mount_spec, "port");
+ if (port_str == NULL)
+ port = 21;
+ else
+ {
+ /* FIXME: error handling? */
+ port = strtoul (port_str, NULL, 10);
+ }
+
+ ftp->addr = soup_address_new (host, port);
+ ftp->user = g_strdup (g_mount_spec_get (mount_spec, "user"));
+ ftp->has_initial_user = ftp->user != NULL;
+
+ return FALSE;
+}
+
+static void
+do_unmount (GVfsBackend * backend,
+ GVfsJobUnmount *job)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+
+ g_mutex_lock (ftp->mutex);
+ while ((conn = g_queue_pop_head (ftp->queue)))
+ {
+ /* FIXME: properly quit */
+ ftp_connection_free (conn);
+ }
+ g_queue_free (ftp->queue);
+ ftp->queue = NULL;
+ g_cond_broadcast (ftp->cond);
+ g_mutex_unlock (ftp->mutex);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+error_550_is_directory (FtpConnection *conn, const FtpFile *file)
+{
+ guint response = ftp_connection_send (conn,
+ RESPONSE_PASS_550,
+ "CWD %s", file);
+
+ if (STATUS_GROUP (response) == 2)
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("File is directory"));
+ }
+}
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *file;
+ static const Ftp550Handler open_read_handlers[] = { error_550_is_directory, NULL };
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (!conn)
+ return;
+
+ ftp_connection_ensure_data_connection (conn);
+
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ ftp_connection_send_and_check (conn,
+ RESPONSE_PASS_100 | RESPONSE_FAIL_200,
+ &open_read_handlers[0],
+ file,
+ "RETR %s", file);
+ g_free (file);
+
+ if (ftp_connection_in_error (conn))
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+ else
+ {
+ /* don't push the connection back, it's our handle now */
+ g_vfs_job_open_for_read_set_handle (job, conn);
+ g_vfs_job_open_for_read_set_can_seek (job, FALSE);
+ ftp_connection_pop_job (conn);
+ }
+}
+
+static void
+do_close_read (GVfsBackend * backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn = handle;
+
+ ftp_connection_push_job (conn, G_VFS_JOB (job));
+ ftp_connection_close_data_connection (conn);
+ ftp_connection_receive (conn, 0);
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_read (GVfsBackend * backend,
+ GVfsJobRead * job,
+ GVfsBackendHandle handle,
+ char * buffer,
+ gsize bytes_requested)
+{
+ FtpConnection *conn = handle;
+ gsize n_bytes;
+
+ ftp_connection_push_job (conn, G_VFS_JOB (job));
+
+ soup_socket_read (conn->data,
+ buffer,
+ bytes_requested,
+ &n_bytes,
+ conn->job->cancellable,
+ &conn->error);
+ /* no need to check return value, code will just do the right thing
+ * depenging on wether conn->error is set */
+
+ g_vfs_job_read_set_size (job, n_bytes);
+ ftp_connection_pop_job (conn);
+}
+
+static void
+do_start_write (GVfsBackendFtp *ftp,
+ FtpConnection *conn,
+ GFileCreateFlags flags,
+ const char *format,
+ ...) G_GNUC_PRINTF (4, 5);
+static void
+do_start_write (GVfsBackendFtp *ftp,
+ FtpConnection *conn,
+ GFileCreateFlags flags,
+ const char *format,
+ ...)
+{
+ va_list varargs;
+ guint status;
+
+ /* FIXME: can we honour the flags? */
+
+ ftp_connection_ensure_data_connection (conn);
+
+ va_start (varargs, format);
+ status = ftp_connection_sendv (conn,
+ RESPONSE_PASS_100 | RESPONSE_FAIL_200,
+ format,
+ varargs);
+ va_end (varargs);
+
+ if (ftp_connection_in_error (conn))
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+ else
+ {
+ /* don't push the connection back, it's our handle now */
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (conn->job), conn);
+ g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (conn->job), FALSE);
+ ftp_connection_pop_job (conn);
+ }
+}
+
+static void
+gvfs_backend_ftp_purge_cache_directory (GVfsBackendFtp *ftp,
+ const FtpFile * dir)
+{
+ g_static_rw_lock_writer_lock (&ftp->directory_cache_lock);
+ g_hash_table_remove (ftp->directory_cache, dir);
+ g_static_rw_lock_writer_unlock (&ftp->directory_cache_lock);
+}
+
+static void
+gvfs_backend_ftp_purge_cache_of_file (GVfsBackendFtp *ftp,
+ FtpConnection * conn,
+ const FtpFile * file)
+{
+ char *dirname, *filename;
+ FtpFile *dir;
+
+ filename = ftp_filename_to_gvfs_path (conn, file);
+ dirname = g_path_get_dirname (filename);
+ dir = ftp_filename_from_gvfs_path (conn, dirname);
+
+ gvfs_backend_ftp_purge_cache_directory (ftp, dir);
+
+ g_free (dir);
+ g_free (filename);
+ g_free (dirname);
+}
+
+/* forward declaration */
+static GFileInfo *
+create_file_info (GVfsBackendFtp *ftp, FtpConnection *conn, const char *filename, char **symlink);
+
+static void
+do_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ GFileInfo *info;
+ FtpFile *file;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ info = create_file_info (ftp, conn, filename, NULL);
+ if (info)
+ {
+ g_object_unref (info);
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ goto error;
+ }
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ do_start_write (ftp, conn, flags, "STOR %s", file);
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, file);
+ g_free (file);
+ return;
+
+error:
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_append (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *file;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ do_start_write (ftp, conn, flags, "APPE %s", filename);
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, file);
+ g_free (file);
+ return;
+}
+
+static void
+do_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *file;
+
+ if (make_backup)
+ {
+ /* FIXME: implement! */
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("backups not supported yet"));
+ return;
+ }
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ do_start_write (ftp, conn, flags, "STOR %s", file);
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, file);
+ g_free (file);
+ return;
+}
+
+static void
+do_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn = handle;
+
+ ftp_connection_push_job (conn, G_VFS_JOB (job));
+
+ ftp_connection_close_data_connection (conn);
+ ftp_connection_receive (conn, 0);
+
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ FtpConnection *conn = handle;
+ gsize n_bytes;
+
+ ftp_connection_push_job (conn, G_VFS_JOB (job));
+
+ soup_socket_write (conn->data,
+ buffer,
+ buffer_size,
+ &n_bytes,
+ G_VFS_JOB (job)->cancellable,
+ &conn->error);
+
+ g_vfs_job_write_set_written_size (job, n_bytes);
+ ftp_connection_pop_job (conn);
+}
+
+static GList *
+do_enumerate_directory (FtpConnection *conn)
+{
+ gsize size, n_bytes, bytes_read;
+ SoupSocketIOStatus status;
+ gboolean got_boundary;
+ char *name;
+ GList *list = NULL;
+
+ if (ftp_connection_in_error (conn))
+ return NULL;
+
+ size = 128;
+ bytes_read = 0;
+ name = g_malloc (size);
+
+ do
+ {
+ if (bytes_read + 3 >= size)
+ {
+ if (size >= 16384)
+ {
+ g_set_error_literal (&conn->error, G_IO_ERROR, G_IO_ERROR_FILENAME_TOO_LONG,
+ _("filename too long"));
+ break;
+ }
+ size += 128;
+ name = g_realloc (name, size);
+ }
+ status = soup_socket_read_until (conn->data,
+ name + bytes_read,
+ size - bytes_read - 1,
+ "\n",
+ 1,
+ &n_bytes,
+ &got_boundary,
+ conn->job->cancellable,
+ &conn->error);
+
+ bytes_read += n_bytes;
+ switch (status)
+ {
+ case SOUP_SOCKET_EOF:
+ case SOUP_SOCKET_OK:
+ if (n_bytes == 0)
+ {
+ status = SOUP_SOCKET_EOF;
+ break;
+ }
+ if (got_boundary)
+ {
+ name[bytes_read - 1] = 0;
+ if (bytes_read >= 2 && name[bytes_read - 2] == '\r')
+ name[bytes_read - 2] = 0;
+ DEBUG ("--- %s\n", name);
+ list = g_list_prepend (list, g_strdup (name));
+ bytes_read = 0;
+ }
+ break;
+ case SOUP_SOCKET_ERROR:
+ goto error2;
+ case SOUP_SOCKET_WOULD_BLOCK:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ while (status == SOUP_SOCKET_OK);
+
+ if (bytes_read)
+ {
+ name[bytes_read] = 0;
+ DEBUG ("--- %s\n", name);
+ list = g_list_prepend (list, name);
+ }
+ else
+ g_free (name);
+
+ ftp_connection_close_data_connection (conn);
+ ftp_connection_receive (conn, 0);
+ if (ftp_connection_in_error (conn))
+ goto error;
+
+ return g_list_reverse (list);
+
+error2:
+ ftp_connection_close_data_connection (conn);
+ ftp_connection_receive (conn, 0);
+error:
+ ftp_connection_close_data_connection (conn);
+ g_list_foreach (list, (GFunc) g_free, NULL);
+ g_list_free (list);
+ return NULL;
+}
+
+/* IMPORTANT: SUCK ALARM!
+ * locks ftp->directory_cache_lock but only iff it returns !NULL */
+static const GList *
+enumerate_directory (GVfsBackendFtp *ftp,
+ FtpConnection * conn,
+ const FtpFile * dir,
+ gboolean use_cache)
+{
+ GList *files;
+
+ g_static_rw_lock_reader_lock (&ftp->directory_cache_lock);
+ do {
+ if (use_cache)
+ files = g_hash_table_lookup (ftp->directory_cache, dir);
+ else
+ {
+ use_cache = TRUE;
+ files = NULL;
+ }
+ if (files == NULL)
+ {
+ g_static_rw_lock_reader_unlock (&ftp->directory_cache_lock);
+ ftp->dir_ops->init_data (conn, dir);
+ files = do_enumerate_directory (conn);
+ if (files == NULL)
+ {
+ return NULL;
+ }
+ g_static_rw_lock_writer_lock (&ftp->directory_cache_lock);
+ g_hash_table_insert (ftp->directory_cache, g_strdup ((const char *) dir), files);
+ g_static_rw_lock_writer_unlock (&ftp->directory_cache_lock);
+ files = NULL;
+ g_static_rw_lock_reader_lock (&ftp->directory_cache_lock);
+ }
+ } while (files == NULL);
+
+ return files;
+}
+
+/* NB: This gets a file info for the given object, no matter if it's a dir
+ * or a file */
+static GFileInfo *
+create_file_info (GVfsBackendFtp *ftp, FtpConnection *conn, const char *filename, char **symlink)
+{
+ const GList *walk, *files;
+ char *dirname;
+ FtpFile *dir, *file;
+ GFileInfo *info;
+ gpointer iter;
+
+ if (symlink)
+ *symlink = NULL;
+
+ if (g_str_equal (filename, "/"))
+ return ftp->dir_ops->get_root (conn);
+
+ dirname = g_path_get_dirname (filename);
+ dir = ftp_filename_from_gvfs_path (conn, dirname);
+ g_free (dirname);
+
+ files = enumerate_directory (ftp, conn, dir, TRUE);
+ if (files == NULL)
+ {
+ g_free (dir);
+ return NULL;
+ }
+
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ iter = ftp->dir_ops->iter_new (conn);
+ for (walk = files; walk; walk = walk->next)
+ {
+ info = ftp->dir_ops->iter_process (iter,
+ conn,
+ dir,
+ file,
+ walk->data,
+ symlink);
+ if (info)
+ break;
+ }
+ ftp->dir_ops->iter_free (iter);
+ g_static_rw_lock_reader_unlock (&ftp->directory_cache_lock);
+ g_free (dir);
+ g_free (file);
+ return info;
+}
+
+static GFileInfo *
+resolve_symlink (GVfsBackendFtp *ftp, FtpConnection *conn, GFileInfo *original, const char *filename)
+{
+ GFileInfo *info = NULL;
+ char *symlink, *newlink;
+ guint i;
+ static const char *copy_attributes[] = {
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME,
+ G_FILE_ATTRIBUTE_STANDARD_COPY_NAME,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET
+ };
+
+ if (ftp_connection_in_error (conn))
+ return original;
+
+ /* How many symlinks should we follow?
+ * <alex> maybe 8?
+ */
+ symlink = g_strdup (filename);
+ for (i = 0; i < 8 && symlink; i++)
+ {
+ info = create_file_info (ftp,
+ conn,
+ symlink,
+ &newlink);
+ if (!newlink)
+ break;
+
+ g_free (symlink);
+ symlink = newlink;
+ }
+ g_free (symlink);
+
+ if (ftp_connection_in_error (conn))
+ {
+ g_assert (info == NULL);
+ ftp_connection_clear_error (conn);
+ return original;
+ }
+ if (info == NULL)
+ return original;
+
+ for (i = 0; i < G_N_ELEMENTS (copy_attributes); i++)
+ {
+ GFileAttributeType type;
+ gpointer value;
+
+ if (!g_file_info_get_attribute_data (original,
+ copy_attributes[i],
+ &type,
+ &value,
+ NULL))
+ continue;
+
+ g_file_info_set_attribute (info,
+ copy_attributes[i],
+ type,
+ value);
+ }
+ g_object_unref (original);
+
+ return info;
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags query_flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ GFileInfo *real;
+ char *symlink;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ if (query_flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
+ {
+ real = create_file_info (ftp,
+ conn,
+ filename,
+ NULL);
+ }
+ else
+ {
+ real = create_file_info (ftp,
+ conn,
+ filename,
+ &symlink);
+ if (symlink)
+ {
+ real = resolve_symlink (ftp, conn, real, symlink);
+ g_free (symlink);
+ }
+ }
+
+ if (real)
+ {
+ g_file_info_copy_into (real, info);
+ g_object_unref (real);
+ }
+ else if (!ftp_connection_in_error (conn))
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *dirname,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags query_flags)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ const GList *walk, *files;
+ FtpFile *dir;
+ gpointer iter;
+ GSList *symlink_targets = NULL;
+ GSList *symlink_fileinfos = NULL;
+ GSList *twalk, *fwalk;
+ GFileInfo *info;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ /* no need to check for IS_DIR, because the enumeration code will return that
+ * automatically.
+ */
+
+ dir = ftp_filename_from_gvfs_path (conn, dirname);
+ files = enumerate_directory (ftp, conn, dir, FALSE);
+ if (ftp_connection_pop_job (conn))
+ {
+ ftp_connection_push_job (conn, G_VFS_JOB (job));
+ if (files != NULL)
+ {
+ iter = ftp->dir_ops->iter_new (conn);
+ for (walk = files; walk; walk = walk->next)
+ {
+ char *symlink = NULL;
+ info = ftp->dir_ops->iter_process (iter,
+ conn,
+ dir,
+ NULL,
+ walk->data,
+ query_flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS ? NULL : &symlink);
+ if (symlink)
+ {
+ /* This is necessary due to our locking.
+ * And we must not unlock here because it might invalidate the list we iterate */
+ symlink_targets = g_slist_prepend (symlink_targets, symlink);
+ symlink_fileinfos = g_slist_prepend (symlink_fileinfos, info);
+ }
+ else if (info)
+ {
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+ }
+ ftp->dir_ops->iter_free (iter);
+ g_static_rw_lock_reader_unlock (&ftp->directory_cache_lock);
+ for (twalk = symlink_targets, fwalk = symlink_fileinfos; twalk;
+ twalk = twalk->next, fwalk = fwalk->next)
+ {
+ info = resolve_symlink (ftp, conn, fwalk->data, twalk->data);
+ g_free (twalk->data);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+ g_slist_free (symlink_targets);
+ g_slist_free (symlink_fileinfos);
+ }
+
+ g_vfs_job_enumerate_done (job);
+ conn->job = NULL;
+ ftp_connection_clear_error (conn);
+ }
+ else
+ g_assert (files == NULL);
+
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+ g_free (dir);
+}
+
+static void
+do_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ char *name;
+ FtpFile *original, *dir, *now;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ original = ftp_filename_from_gvfs_path (conn, filename);
+ name = g_path_get_dirname (filename);
+ dir = ftp_filename_from_gvfs_path (conn, name);
+ g_free (name);
+ now = ftp_filename_construct (conn, dir, display_name);
+ if (now == NULL)
+ {
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Invalid filename"));
+ }
+ ftp_connection_send (conn,
+ RESPONSE_PASS_300 | RESPONSE_FAIL_200,
+ "RNFR %s", original);
+ g_free (original);
+ ftp_connection_send (conn,
+ 0,
+ "RNTO %s", now);
+
+ name = ftp_filename_to_gvfs_path (conn, now);
+ g_free (now);
+ g_vfs_job_set_display_name_set_new_path (job, name);
+ g_free (name);
+ gvfs_backend_ftp_purge_cache_directory (ftp, dir);
+ g_free (dir);
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *file;
+ guint response;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ /* We try file deletion first. If that fails, we try directory deletion.
+ * The file-first-then-directory order has been decided by coin-toss. */
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ response = ftp_connection_send (conn,
+ RESPONSE_PASS_500,
+ "DELE %s", file);
+ if (STATUS_GROUP (response) == 5)
+ {
+ response = ftp_connection_send (conn,
+ RESPONSE_PASS_500,
+ "RMD %s", file);
+ if (response == 550)
+ {
+ const GList *files = enumerate_directory (ftp, conn, file, FALSE);
+ if (files)
+ {
+ g_static_rw_lock_reader_unlock (&ftp->directory_cache_lock);
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_EMPTY,
+ g_strerror (ENOTEMPTY));
+ }
+ else
+ ftp_connection_set_error_from_response (conn, response);
+ }
+ else if (STATUS_GROUP (response) == 5)
+ {
+ ftp_connection_set_error_from_response (conn, response);
+ }
+ }
+
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, file);
+ g_free (file);
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *file;
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ file = ftp_filename_from_gvfs_path (conn, filename);
+ ftp_connection_send (conn,
+ 0,
+ "MKD %s", file);
+ /* FIXME: Compare created file with name from server result to be sure
+ * it's correct and otherwise fail. */
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, file);
+ g_free (file);
+
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+do_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
+ FtpConnection *conn;
+ FtpFile *srcfile, *destfile;
+
+ /* FIXME: what about G_FILE_COPY_NOFOLLOW_SYMLINKS and G_FILE_COPY_ALL_METADATA? */
+
+ if (flags & G_FILE_COPY_BACKUP)
+ {
+ /* FIXME: implement! */
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("backups not supported yet"));
+ return;
+ }
+
+ conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
+ if (conn == NULL)
+ return;
+
+ srcfile = ftp_filename_from_gvfs_path (conn, source);
+ destfile = ftp_filename_from_gvfs_path (conn, destination);
+ if (ftp_connection_try_cd (conn, destfile))
+ {
+ char *basename = g_path_get_basename (source);
+ FtpFile *real = ftp_filename_construct (conn, destfile, basename);
+
+ g_free (basename);
+ if (real == NULL)
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME,
+ _("Invalid destination filename"));
+ else
+ {
+ g_free (destfile);
+ destfile = real;
+ }
+ }
+
+ if (!(flags & G_FILE_COPY_OVERWRITE))
+ {
+ char *destfilename = ftp_filename_to_gvfs_path (conn, destfile);
+ GFileInfo *info = create_file_info (ftp, conn, destfilename, NULL);
+
+ g_free (destfilename);
+ if (info)
+ {
+ g_object_unref (info);
+ g_set_error_literal (&conn->error,
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ goto out;
+ }
+ }
+
+ ftp_connection_send (conn,
+ RESPONSE_PASS_300 | RESPONSE_FAIL_200,
+ "RNFR %s", srcfile);
+ ftp_connection_send (conn,
+ 0,
+ "RNTO %s", destfile);
+
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, srcfile);
+ gvfs_backend_ftp_purge_cache_of_file (ftp, conn, destfile);
+out:
+ g_free (srcfile);
+ g_free (destfile);
+ g_vfs_backend_ftp_push_connection (ftp, conn);
+}
+
+static void
+g_vfs_backend_ftp_class_init (GVfsBackendFtpClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_ftp_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->try_mount = try_mount;
+ backend_class->unmount = do_unmount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->close_read = do_close_read;
+ backend_class->read = do_read;
+ backend_class->create = do_create;
+ backend_class->append_to = do_append;
+ backend_class->replace = do_replace;
+ backend_class->close_write = do_close_write;
+ backend_class->write = do_write;
+ backend_class->query_info = do_query_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->set_display_name = do_set_display_name;
+ backend_class->delete = do_delete;
+ backend_class->make_directory = do_make_directory;
+ backend_class->move = do_move;
+}
diff --git a/trunk/daemon/gvfsbackendftp.h b/trunk/daemon/gvfsbackendftp.h
new file mode 100644
index 00000000..23538342
--- /dev/null
+++ b/trunk/daemon/gvfsbackendftp.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_FTP_H__
+#define __G_VFS_BACKEND_FTP_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_FTP (g_vfs_backend_ftp_get_type ())
+#define G_VFS_BACKEND_FTP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_FTP, GVfsBackendFtp))
+#define G_VFS_BACKEND_FTP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_FTP, GVfsBackendFtpClass))
+#define G_VFS_IS_BACKEND_FTP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_FTP))
+#define G_VFS_IS_BACKEND_FTP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_FTP))
+#define G_VFS_BACKEND_FTP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_FTP, GVfsBackendFtpClass))
+
+typedef struct _GVfsBackendFtp GVfsBackendFtp;
+typedef struct _GVfsBackendFtpClass GVfsBackendFtpClass;
+
+struct _GVfsBackendFtpClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_ftp_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_FTP_H__ */
diff --git a/trunk/daemon/gvfsbackendgphoto2.c b/trunk/daemon/gvfsbackendgphoto2.c
new file mode 100644
index 00000000..a21df894
--- /dev/null
+++ b/trunk/daemon/gvfsbackendgphoto2.c
@@ -0,0 +1,3428 @@
+
+/* GVFS gphoto2 file system driver
+ *
+ * Copyright (C) 2007-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gphoto2.h>
+#include <libhal.h>
+#include <dbus/dbus.h>
+#include <sys/time.h>
+
+#include "gvfsbackendgphoto2.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobopeniconforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsmonitor.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsicon.h"
+
+/* showing debug traces */
+#if 0
+#define DEBUG_SHOW_TRACES 1
+#endif
+
+/* showing libgphoto2 output */
+#if 0
+#define DEBUG_SHOW_LIBGPHOTO2_OUTPUT 1
+#endif
+
+/* use this to disable caching */
+#if 0
+#define DEBUG_NO_CACHING 1
+#endif
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+/* TODO:
+ *
+ * - write support
+ * - it's in; we support writing. yay.
+ * - though there's no way to rename an non-empty folder yet
+ * - there's an assumption, for caching, that the device won't
+ * be able to put files while we're using it. May have to
+ * revisit that if such devices exist.
+ * - one solution: make cache items valid for only five seconds or something
+ *
+ * - Note that most PTP devices (e.g. digital cameras) don't support writing
+ * - Most MTP devices (e.g. digital audio players) do
+ *
+ * - However, some MTP devices are just busted when using ~ backup
+ * style; see below. This is with my (davidz) Sandisk Sansa
+ * e250. This is probably a firmware bug; when investigating
+ * libgphoto2 reports everything as peachy.
+ *
+ * $ pwd
+ * /home/davidz/.gvfs/gphoto2 mount on usb%3A001,051/foo
+ * $ echo a > a
+ * $ echo b > b
+ * $ ls -l
+ * total 0
+ * -rw------- 1 davidz davidz 2 2008-03-02 13:22 a
+ * -rw------- 1 davidz davidz 2 2008-03-02 13:22 b
+ * $ cat a
+ * a
+ * $ cat b
+ * b
+ * $ mv b a
+ * $ ls -l
+ * total 0
+ * -rw------- 1 davidz davidz 2 2008-03-02 13:22 a
+ * $ cat a
+ * b
+ * $ rm a
+ *
+ * See, this worked fine.. Now see what happens if we
+ * use different files names
+ *
+ * $ echo a > file.txt
+ * $ echo b > file.txt~
+ * $ ls -l
+ * total 0
+ * -rw------- 1 davidz davidz 2 2008-03-02 13:22 file.txt
+ * -rw------- 1 davidz davidz 2 2008-03-02 13:22 file.txt~
+ * $ cat file.txt
+ * a
+ * $ cat file.txt~
+ * b
+ * $ mv file.txt~ file.txt
+ * $ ls -l
+ * total 0
+ * -rw------- 1 davidz davidz 0 1969-12-31 18:59 file.txt
+ * $ cat file.txt
+ * $
+ *
+ * Awesome. I hate hardware.
+ *
+ * - This is a bit bad as it affects most text editors (vim, emacs,
+ * gedit) and it actually results in data loss. However, there's
+ * little we can do about it.
+ *
+ * - Would be nice to test this on other MTP devices to verify
+ * it's indeed a firmware bug in the Sansa Sandisk e250.
+ *
+ * - This shouldn't affect stuff like Banshee or Rhythmbox using
+ * this backend for MTP support though; despite this bug basic
+ * file operations works nicely.
+ * - http://bugzilla.gnome.org/show_bug.cgi?id=520121
+ *
+ * - Need to test this with a native gio version of gedit that should
+ * use replace() directly instead of fooling around with ~-style
+ * backup files
+ *
+ * - adding a payload cache don't make much sense as libgphoto2 has a LRU cache already
+ * - (see comment in the do_close_write() function)
+ *
+ * - Support PTP/IP devices nicely
+ * - Need hardware for testing
+ * - Should actually work out of the box; just try mounting e.g.
+ * gphoto2://[ptpip:<something]/ from either Nautilus or via
+ * gvfs-mount(1).
+ * - Need to automatically unmount when the device stops answering
+ * - May need authentication bits
+ * - Need integration into network://
+ * - does such devices use DNS-SD or UPNP?
+ *
+ */
+
+struct _GVfsBackendGphoto2
+{
+ GVfsBackend parent_instance;
+
+ /* a gphoto2 specific identifier for the gphoto2 camera such as usb:001,041 */
+ char *gphoto2_port;
+ GPContext *context;
+ Camera *camera;
+
+ /* see comment in ensure_ignore_prefix() */
+ char *ignore_prefix;
+
+ /* list of open files */
+ int num_open_files_for_reading;
+
+ DBusConnection *dbus_connection;
+ LibHalContext *hal_ctx;
+ char *hal_udi;
+ char *hal_name;
+ char *hal_icon_name;
+
+ /* whether we can write to the device */
+ gboolean can_write;
+
+ /* This lock protects all members in this class that are not
+ * used both on the main thread and on the IO thread.
+ *
+ * It is used, among other places, in the try_* functions to return
+ * already cached data quickly (to e.g. enumerate and get file info
+ * while we're reading or writing a file from the device).
+ *
+ * Must only be held for very short amounts of time (e.g. no IO).
+ */
+ GMutex *lock;
+
+ /* CACHES */
+
+ /* free_space is set to -1 if we don't know or have modified the
+ * device since last time we read it. If -1 we can't do
+ * try_query_fs_info() and will fall back to do_query_fs_info().
+ */
+ gint64 free_space;
+ gint64 capacity;
+
+ /* fully qualified path -> GFileInfo */
+ GHashTable *info_cache;
+
+ /* dir name -> CameraList of (sub-) directory names in given directory */
+ GHashTable *dir_name_cache;
+
+ /* dir name -> CameraList of file names in given directory */
+ GHashTable *file_name_cache;
+
+ /* monitors (only used on the IO thread) */
+ GList *dir_monitor_proxies;
+ GList *file_monitor_proxies;
+
+ /* list of open write handles (only used on the IO thread) */
+ GList *open_write_handles;
+};
+
+G_DEFINE_TYPE (GVfsBackendGphoto2, g_vfs_backend_gphoto2, G_VFS_TYPE_BACKEND);
+
+/* ------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+ /* this is the path of the dir/file including ignore_prefix */
+ char *path;
+ GVfsMonitor *vfs_monitor;
+} MonitorProxy;
+
+static void
+monitor_proxy_free (MonitorProxy *proxy)
+{
+ g_free (proxy->path);
+ /* vfs_monitor is owned by the gvfs core; see the functions
+ * vfs_dir_monitor_destroyed() and do_create_monitor()
+ */
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+ /* filename as given from the vfs without ignore prefix e.g. /foo.txt */
+ char *filename;
+
+ /* filename with ignore prefix splitted into dir and name; e.g. "/store_00010001/" and "foo.txt" */
+ char *dir;
+ char *name;
+
+ char *data;
+ unsigned long int size;
+ unsigned long int cursor;
+ unsigned long int allocated_size;
+
+ gboolean job_is_replace;
+ gboolean job_is_append_to;
+
+ gboolean delete_before;
+
+ gboolean is_dirty;
+} WriteHandle;
+
+/* how much more memory to ask for when using g_realloc() when writing a file */
+#define WRITE_INCREMENT 4096
+
+typedef struct {
+ CameraFile *file;
+
+ const char *data;
+ unsigned long int size;
+ unsigned long int cursor;
+} ReadHandle;
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+DEBUG (const gchar *message, ...)
+{
+#ifdef DEBUG_SHOW_TRACES
+ va_list args;
+ va_start (args, message);
+ g_vfprintf (stderr, message, args);
+ va_end (args);
+ g_fprintf (stderr, "\n");
+ fflush (stderr);
+#endif
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static int commit_write_handle (GVfsBackendGphoto2 *gphoto2_backend, WriteHandle *write_handle);
+
+static void
+write_handle_free (WriteHandle *write_handle)
+{
+ g_free (write_handle->filename);
+ g_free (write_handle->dir);
+ g_free (write_handle->name);
+ g_free (write_handle->data);
+ g_free (write_handle);
+}
+
+/* This must be called before reading from the device to ensure that
+ * all pending writes are written to the device.
+ *
+ * Must only be called on the IO thread.
+ */
+static void
+ensure_not_dirty (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ GList *l;
+
+ for (l = gphoto2_backend->open_write_handles; l != NULL; l = l->next)
+ {
+ WriteHandle *write_handle = l->data;
+
+ DEBUG ("ensure_not_dirty: looking at handle for '%s", write_handle->filename);
+
+ if (write_handle->is_dirty)
+ commit_write_handle (gphoto2_backend, write_handle);
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* used when gphoto2 will take ownership of this data for it's LRU cache - and will use free(3) to free it */
+static char *
+dup_for_gphoto2 (char *gmem, unsigned long int size)
+{
+ char *mem;
+ mem = malloc (size);
+ memcpy (mem, gmem, size);
+ return mem;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+monitors_emit_internal (GVfsBackendGphoto2 *gphoto2_backend,
+ const char *dir,
+ const char *name,
+ GFileMonitorEvent event,
+ const char *event_name)
+{
+ GList *l;
+ char *filepath;
+
+ g_return_if_fail (g_str_has_prefix (dir, gphoto2_backend->ignore_prefix));
+
+ DEBUG ("monitors_emit_internal() %s for '%s' '%s'", event_name, dir, name);
+
+ for (l = gphoto2_backend->dir_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ if (strcmp (proxy->path, dir) == 0)
+ {
+ char *path;
+ path = g_build_filename (dir + strlen (gphoto2_backend->ignore_prefix), name, NULL);
+ g_vfs_monitor_emit_event (proxy->vfs_monitor, event, path, NULL);
+ DEBUG (" emitted %s for '%s' on dir monitor for '%s'", event_name, path, dir);
+ g_free (path);
+ }
+ }
+
+ filepath = g_build_filename (dir, name, NULL);
+ for (l = gphoto2_backend->file_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ if (strcmp (proxy->path, filepath) == 0)
+ {
+ const char *path = filepath + strlen (gphoto2_backend->ignore_prefix);
+ g_vfs_monitor_emit_event (proxy->vfs_monitor, event, path, NULL);
+ DEBUG (" emitted %s for '%s' on file monitor", event_name, path);
+ }
+ }
+ g_free (filepath);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* call this when a file/directory have been added to a directory */
+static void
+monitors_emit_created (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ DEBUG ("monitors_emit_created(): '%s' '%s'", dir, name);
+ monitors_emit_internal (gphoto2_backend, dir, name, G_FILE_MONITOR_EVENT_CREATED, "CREATED");
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* call this when a file/directory have been deleted from a directory */
+static void
+monitors_emit_deleted (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ DEBUG ("monitors_emit_deleted(): '%s' '%s'", dir, name);
+ monitors_emit_internal (gphoto2_backend, dir, name, G_FILE_MONITOR_EVENT_DELETED, "DELETED");
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* call this when a file/directory have been changed in a directory */
+static void
+monitors_emit_changed (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ DEBUG ("monitors_emit_changed(): '%s' '%s'", dir, name);
+ monitors_emit_internal (gphoto2_backend, dir, name, G_FILE_MONITOR_EVENT_CHANGED, "CHANGED");
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+caches_invalidate_all (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ DEBUG ("caches_invalidate_all()");
+
+ g_mutex_lock (gphoto2_backend->lock);
+ if (gphoto2_backend->dir_name_cache != NULL)
+ g_hash_table_remove_all (gphoto2_backend->dir_name_cache);
+ if (gphoto2_backend->file_name_cache != NULL)
+ g_hash_table_remove_all (gphoto2_backend->file_name_cache);
+ if (gphoto2_backend->info_cache != NULL)
+ g_hash_table_remove_all (gphoto2_backend->info_cache);
+ gphoto2_backend->capacity = -1;
+ gphoto2_backend->free_space = -1;
+ g_mutex_unlock (gphoto2_backend->lock);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+caches_invalidate_free_space (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ g_mutex_lock (gphoto2_backend->lock);
+ gphoto2_backend->free_space = -1;
+ g_mutex_unlock (gphoto2_backend->lock);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+caches_invalidate_dir (GVfsBackendGphoto2 *gphoto2_backend, const char *dir)
+{
+ DEBUG ("caches_invalidate_dir() for '%s'", dir);
+ g_mutex_lock (gphoto2_backend->lock);
+ g_hash_table_remove (gphoto2_backend->dir_name_cache, dir);
+ g_hash_table_remove (gphoto2_backend->file_name_cache, dir);
+ g_hash_table_remove (gphoto2_backend->info_cache, dir);
+ g_mutex_unlock (gphoto2_backend->lock);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+caches_invalidate_file (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ char *full_name;
+
+ full_name = g_build_filename (dir, name, NULL);
+
+ g_mutex_lock (gphoto2_backend->lock);
+ /* this is essentially: caches_invalidate_dir (gphoto2_backend, dir); */
+ g_hash_table_remove (gphoto2_backend->dir_name_cache, dir);
+ g_hash_table_remove (gphoto2_backend->file_name_cache, dir);
+ g_hash_table_remove (gphoto2_backend->info_cache, dir);
+
+ g_hash_table_remove (gphoto2_backend->info_cache, full_name);
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ DEBUG ("caches_invalidate_file() for '%s'", full_name);
+ g_free (full_name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static GError *
+get_error_from_gphoto2 (const char *message, int rc)
+{
+ GError *error;
+
+ switch (rc)
+ {
+ case GP_ERROR_FILE_EXISTS:
+ case GP_ERROR_DIRECTORY_EXISTS:
+ /* Translator: %s represents a more specific error message and %d the specific error code */
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_EXISTS, _("%s: %d: Directory or file exists"), message, rc);
+ break;
+
+ case GP_ERROR_FILE_NOT_FOUND:
+ case GP_ERROR_DIRECTORY_NOT_FOUND:
+ /* Translator: %s represents a more specific error message and %d the specific error code */
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND, _("%s: %d: No such file or directory"), message, rc);
+ break;
+
+ case GP_ERROR_PATH_NOT_ABSOLUTE:
+ /* Translator: %s represents a more specific error message and %d the specific error code */
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME, _("%s: %d: Invalid filename"), message, rc);
+ break;
+
+ case GP_ERROR_NOT_SUPPORTED:
+ /* Translator: %s represents a more specific error message and %d the specific error code */
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED, _("%s: %d: Not Supported"), message, rc);
+ break;
+
+ default:
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_FAILED, "%s: %d: %s", message, rc, gp_result_as_string (rc));
+ break;
+ }
+ return error;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+release_device (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ GList *l;
+
+ g_free (gphoto2_backend->gphoto2_port);
+ gphoto2_backend->gphoto2_port = NULL;
+
+ if (gphoto2_backend->context != NULL)
+ {
+ gp_context_unref (gphoto2_backend->context);
+ gphoto2_backend->context = NULL;
+ }
+
+ if (gphoto2_backend->camera != NULL)
+ {
+ gp_camera_unref (gphoto2_backend->camera);
+ gphoto2_backend->camera = NULL;
+ }
+
+ if (gphoto2_backend->dbus_connection != NULL)
+ {
+ dbus_connection_close (gphoto2_backend->dbus_connection);
+ dbus_connection_unref (gphoto2_backend->dbus_connection);
+ gphoto2_backend->dbus_connection = NULL;
+ }
+
+ if (gphoto2_backend->hal_ctx != NULL)
+ {
+ libhal_ctx_free (gphoto2_backend->hal_ctx);
+ gphoto2_backend->hal_ctx = NULL;
+
+ }
+ g_free (gphoto2_backend->hal_udi);
+ gphoto2_backend->hal_udi = NULL;
+ g_free (gphoto2_backend->hal_name);
+ gphoto2_backend->hal_name = NULL;
+ g_free (gphoto2_backend->hal_icon_name);
+ gphoto2_backend->hal_icon_name = NULL;
+
+ g_free (gphoto2_backend->ignore_prefix);
+ gphoto2_backend->ignore_prefix = NULL;
+
+ if (gphoto2_backend->info_cache != NULL)
+ {
+ g_hash_table_unref (gphoto2_backend->info_cache);
+ gphoto2_backend->info_cache = NULL;
+ }
+ if (gphoto2_backend->dir_name_cache != NULL)
+ {
+ g_hash_table_unref (gphoto2_backend->dir_name_cache);
+ gphoto2_backend->dir_name_cache = NULL;
+ }
+ if (gphoto2_backend->file_name_cache != NULL)
+ {
+ g_hash_table_unref (gphoto2_backend->file_name_cache);
+ gphoto2_backend->file_name_cache = NULL;
+ }
+
+ for (l = gphoto2_backend->dir_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ monitor_proxy_free (proxy);
+ }
+ g_list_free (gphoto2_backend->dir_monitor_proxies);
+ gphoto2_backend->dir_monitor_proxies = NULL;
+
+ for (l = gphoto2_backend->file_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ monitor_proxy_free (proxy);
+ }
+ g_list_free (gphoto2_backend->file_monitor_proxies);
+ gphoto2_backend->file_monitor_proxies = NULL;
+
+ if (gphoto2_backend->lock != NULL)
+ {
+ g_mutex_free (gphoto2_backend->lock);
+ gphoto2_backend->lock = NULL;
+ }
+ gphoto2_backend->capacity = -1;
+ gphoto2_backend->free_space = -1;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+g_vfs_backend_gphoto2_finalize (GObject *object)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (object);
+
+ DEBUG ("finalizing %p", object);
+
+ release_device (gphoto2_backend);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_gphoto2_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_gphoto2_parent_class)->finalize) (object);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+#ifdef DEBUG_SHOW_LIBGPHOTO2_OUTPUT
+static void
+_gphoto2_logger_func (GPLogLevel level, const char *domain, const char *format, va_list args, void *data)
+{
+ g_fprintf (stderr, "libgphoto2: %s: ", domain);
+ g_vfprintf (stderr, message, args);
+ va_end (args);
+ g_fprintf (stderr, "\n");
+}
+#endif
+
+static void
+g_vfs_backend_gphoto2_init (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (gphoto2_backend);
+ GMountSpec *mount_spec;
+
+ DEBUG ("initing %p", gphoto2_backend);
+
+ g_vfs_backend_set_display_name (backend, "gphoto2");
+
+ mount_spec = g_mount_spec_new ("gphoto2");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+
+#ifdef DEBUG_SHOW_LIBGPHOTO2_OUTPUT
+ gp_log_add_func (GP_LOG_ALL, _gphoto2_logger_func, NULL);
+#endif
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static char *
+compute_icon_name (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ char *result;
+
+ if (gphoto2_backend->hal_icon_name == NULL)
+ {
+ result = g_strdup_printf ("camera-photo");
+ }
+ else
+ {
+ result = g_strdup (gphoto2_backend->hal_icon_name);
+ }
+
+ return result;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static char *
+compute_display_name (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ char *result;
+
+ if (gphoto2_backend->hal_name == NULL)
+ {
+ /* Translator: %s represents the device, e.g. usb:001,042 */
+ result = g_strdup_printf (_("Digital Camera (%s)"), gphoto2_backend->gphoto2_port);
+ }
+ else
+ {
+ result = g_strdup (gphoto2_backend->hal_name);
+ }
+
+ return result;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+find_udi_for_device (GVfsBackendGphoto2 *gphoto2_backend)
+{
+ int num_camera_devices;
+ int num_mtp_devices;
+ int num_devices;
+ char **camera_devices;
+ char **mtp_devices;
+ char **devices;
+ int n, m;
+ int usb_bus_num;
+ int usb_device_num;
+ char **tokens;
+ char *endp;
+ char *camera_x_content_types[] = {"x-content/image-dcf", NULL};
+ char *music_player_x_content_types[] = {"x-content/audio-player", NULL};
+
+ gphoto2_backend->hal_udi = NULL;
+
+ /* parse the usb:001,041 string */
+
+ if (!g_str_has_prefix (gphoto2_backend->gphoto2_port, "usb:"))
+ {
+ return;
+ }
+
+ tokens = g_strsplit (gphoto2_backend->gphoto2_port + 4, ",", 0);
+ if (g_strv_length (tokens) != 2)
+ {
+ g_strfreev (tokens);
+ return;
+ }
+
+ usb_bus_num = strtol (tokens[0], &endp, 10);
+ if (*endp != '\0')
+ {
+ g_strfreev (tokens);
+ return;
+ }
+
+ usb_device_num = strtol (tokens[1], &endp, 10);
+ if (*endp != '\0')
+ {
+ g_strfreev (tokens);
+ return;
+ }
+
+ g_strfreev (tokens);
+
+ DEBUG ("Parsed '%s' into bus=%d device=%d", gphoto2_backend->gphoto2_port, usb_bus_num, usb_device_num);
+
+ camera_devices = libhal_find_device_by_capability (gphoto2_backend->hal_ctx,
+ "camera",
+ &num_camera_devices,
+ NULL);
+ mtp_devices = libhal_find_device_by_capability (gphoto2_backend->hal_ctx,
+ "portable_audio_player",
+ &num_mtp_devices,
+ NULL);
+ for (m = 0; m < 2 && gphoto2_backend->hal_udi == NULL; m++)
+ {
+ devices = m == 0 ? camera_devices : mtp_devices;
+ num_devices = m == 0 ? num_camera_devices : num_mtp_devices;
+
+ if (devices != NULL)
+ {
+ for (n = 0; n < num_devices && gphoto2_backend->hal_udi == NULL; n++)
+ {
+ char *udi = devices[n];
+ LibHalPropertySet *ps;
+
+ ps = libhal_device_get_all_properties (gphoto2_backend->hal_ctx, udi, NULL);
+ if (ps != NULL)
+ {
+ const char *subsystem;
+
+ subsystem = libhal_ps_get_string (ps, "info.subsystem");
+ if (subsystem != NULL && strcmp (subsystem, "usb") == 0)
+ {
+ int device_usb_bus_num;
+ int device_usb_device_num;
+ const char *icon_from_hal;
+ const char *name_from_hal;
+
+ device_usb_bus_num = libhal_ps_get_int32 (ps, "usb.bus_number");
+ device_usb_device_num = libhal_ps_get_int32 (ps, "usb.linux.device_number");
+ icon_from_hal = libhal_ps_get_string (ps, "info.desktop.icon");
+ name_from_hal = libhal_ps_get_string (ps, "info.desktop.name");
+
+ DEBUG ("looking at usb device '%s' with bus=%d, device=%d",
+ udi, device_usb_bus_num, device_usb_device_num);
+
+ if (device_usb_bus_num == usb_bus_num &&
+ device_usb_device_num == usb_device_num)
+ {
+ char *name;
+ const char *parent_udi;
+ LibHalPropertySet *ps2;
+
+ DEBUG ("udi '%s' is the one!", udi);
+
+ /* IMPORTANT:
+ *
+ * Keep this naming code in sync with
+ *
+ * hal/ghalvolume;do_update_from_hal_for_camera()
+ */
+ name = NULL;
+ parent_udi = libhal_ps_get_string (ps, "info.parent");
+ if (name_from_hal != NULL)
+ {
+ name = g_strdup (name_from_hal);
+ }
+ else if (parent_udi != NULL)
+ {
+ ps2 = libhal_device_get_all_properties (gphoto2_backend->hal_ctx, parent_udi, NULL);
+ if (ps2 != NULL)
+ {
+ const char *vendor;
+ const char *product;
+
+ vendor = libhal_ps_get_string (ps2, "usb_device.vendor");
+ product = libhal_ps_get_string (ps2, "usb_device.product");
+ if (vendor == NULL)
+ {
+ if (product != NULL)
+ name = g_strdup (product);
+ }
+ else
+ {
+ if (product != NULL)
+ name = g_strdup_printf ("%s %s", vendor, product);
+ else
+ {
+ if (m == 0)
+ /* Translator: %s is the vendor name, e.g. Panasonic */
+ name = g_strdup_printf (_("%s Camera"), vendor);
+ else
+ /* Translator: %s is the vendor name, e.g. Panasonic */
+ name = g_strdup_printf (_("%s Audio Player"), vendor);
+ }
+ }
+ libhal_free_property_set (ps2);
+ }
+ }
+ if (name == NULL)
+ {
+ if (m == 0)
+ name = g_strdup (_("Camera"));
+ else
+ name = g_strdup (_("Audio Player"));
+ }
+
+ gphoto2_backend->hal_udi = g_strdup (udi);
+ gphoto2_backend->hal_name = name;
+ if (icon_from_hal != NULL)
+ {
+ gphoto2_backend->hal_icon_name = g_strdup (icon_from_hal);
+ }
+ else
+ {
+ if (m == 1)
+ {
+ gphoto2_backend->hal_icon_name = g_strdup ("multimedia-player");
+ }
+ else
+ {
+ gphoto2_backend->hal_icon_name = g_strdup ("camera-photo");
+ }
+ }
+
+ /* TODO: should we sniff the files instead? */
+ if (m == 0)
+ {
+ g_vfs_backend_set_x_content_types (G_VFS_BACKEND (gphoto2_backend),
+ camera_x_content_types);
+ }
+ else
+ {
+ g_vfs_backend_set_x_content_types (G_VFS_BACKEND (gphoto2_backend),
+ music_player_x_content_types);
+ }
+
+ }
+
+ }
+
+ libhal_free_property_set (ps);
+ }
+ }
+ libhal_free_string_array (devices);
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+_hal_device_removed (LibHalContext *hal_ctx, const char *udi)
+{
+ GVfsBackendGphoto2 *gphoto2_backend;
+
+ gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (libhal_ctx_get_user_data (hal_ctx));
+
+ if (gphoto2_backend->hal_udi != NULL && strcmp (udi, gphoto2_backend->hal_udi) == 0)
+ {
+ DEBUG ("we have been removed!");
+
+ /* nuke all caches so we're a bit more valgrind friendly */
+ caches_invalidate_all (gphoto2_backend);
+
+ /* TODO: need a cleaner way to force unmount ourselves */
+ exit (1);
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+split_filename_with_ignore_prefix (GVfsBackendGphoto2 *gphoto2_backend, const char *filename, char **dir, char **name)
+{
+ char *s;
+
+ s = g_path_get_dirname (filename);
+ if (s[0] == '/')
+ *dir = g_strconcat (gphoto2_backend->ignore_prefix, s + 1, NULL);
+ else
+ *dir = g_strconcat (gphoto2_backend->ignore_prefix, s, NULL);
+ g_free (s);
+
+ if (strcmp (filename, "/") == 0)
+ *name = g_strdup ("");
+ else
+ *name = g_path_get_basename (filename);
+
+ s = *dir;
+ if (s[strlen(s)] == '/')
+ s[strlen(s)] = '\0';
+
+ /*DEBUG ("split_filename_with_ignore_prefix: '%s' -> '%s' '%s'", filename, *dir, *name);*/
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static char *
+add_ignore_prefix (GVfsBackendGphoto2 *gphoto2_backend, const char *filename)
+{
+ char *result;
+
+ if (filename[0] == '/')
+ result = g_strconcat (gphoto2_backend->ignore_prefix, filename + 1, NULL);
+ else
+ result = g_strconcat (gphoto2_backend->ignore_prefix, filename, NULL);
+
+ /*DEBUG ("add_ignore_prefix: '%s' -> '%s'", filename, result);*/
+ return result;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* the passed 'dir' variable must contain ignore_prefix */
+static gboolean
+file_get_info (GVfsBackendGphoto2 *gphoto2_backend,
+ const char *dir,
+ const char *name,
+ GFileInfo *info,
+ GError **error,
+ gboolean try_cache_only)
+{
+ int rc;
+ gboolean ret;
+ CameraFileInfo gp_info;
+ char *full_path;
+ GFileInfo *cached_info;
+ GTimeVal mtime;
+ char *mime_type;
+ GIcon *icon;
+ unsigned int n;
+
+ ret = FALSE;
+
+ full_path = g_build_filename (dir, name, NULL);
+ DEBUG ("file_get_info() try_cache_only=%d dir='%s', name='%s'\n"
+ " full_path='%s'",
+ try_cache_only, dir, name, full_path, gphoto2_backend->ignore_prefix);
+
+
+ /* first look up cache */
+ g_mutex_lock (gphoto2_backend->lock);
+ cached_info = g_hash_table_lookup (gphoto2_backend->info_cache, full_path);
+ if (cached_info != NULL)
+ {
+ g_file_info_copy_into (cached_info, info);
+ g_mutex_unlock (gphoto2_backend->lock);
+ DEBUG (" Using cached info %p for '%s'", cached_info, full_path);
+ ret = TRUE;
+ goto out;
+ }
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ if (try_cache_only)
+ goto out;
+
+ ensure_not_dirty (gphoto2_backend);
+
+ DEBUG (" No cached info for '%s'", full_path);
+
+ /* Since we're caching stuff, make sure all information we store is set */
+ g_file_info_unset_attribute_mask (info);
+
+ /* handle root directory */
+ if (strcmp (full_path, gphoto2_backend->ignore_prefix) == 0 || strcmp (full_path, "/") == 0)
+ {
+ char *display_name;
+ display_name = compute_display_name (gphoto2_backend);
+ g_file_info_set_display_name (info, display_name);
+ g_file_info_set_name (info, display_name);
+ g_free (display_name);
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
+ g_file_info_set_size (info, 0);
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+ ret = TRUE;
+ DEBUG (" Generating info (root folder) for '%s'", full_path);
+ goto add_to_cache;
+ }
+
+ rc = gp_camera_file_get_info (gphoto2_backend->camera,
+ dir,
+ name,
+ &gp_info,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ CameraList *list;
+ gboolean is_folder;
+
+ /* gphoto2 doesn't know about this file.. it may be a folder; try that */
+ is_folder = FALSE;
+ gp_list_new (&list);
+ rc = gp_camera_folder_list_folders (gphoto2_backend->camera,
+ dir,
+ list,
+ gphoto2_backend->context);
+ if (rc == 0)
+ {
+ for (n = 0; n < gp_list_count (list) && !is_folder; n++)
+ {
+ const char *folder_name;
+ gp_list_get_name (list, n, &folder_name);
+ if (strcmp (folder_name, name) == 0)
+ {
+ is_folder = TRUE;
+ }
+ }
+ }
+ gp_list_free (list);
+
+ if (is_folder)
+ {
+ g_file_info_set_name (info, name);
+ g_file_info_set_display_name (info, name);
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
+ g_file_info_set_size (info, 0);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, gphoto2_backend->can_write);
+ g_file_info_set_is_hidden (info, name != NULL && name[0] == '.');
+ ret = TRUE;
+ DEBUG (" Generating info (folder) for '%s'", full_path);
+ goto add_to_cache;
+ }
+
+ /* nope, not a folder either.. error out.. */
+ if (error != NULL)
+ {
+ *error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ }
+ goto out;
+ }
+
+ g_file_info_set_name (info, name);
+ g_file_info_set_display_name (info, name);
+ g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+
+ if (gp_info.file.fields & GP_FILE_INFO_SIZE)
+ {
+ g_file_info_set_size (info, gp_info.file.size);
+ }
+ else
+ {
+ /* not really sure this is the right thing to do... */
+ g_file_info_set_size (info, 0);
+ }
+
+ /* TODO: We really should sniff the file / look at file extensions
+ * instead of relying on gp_info.file.type... but sniffing the file
+ * is no fun since we (currently) can't do partial reads with the
+ * libgphoto2 API :-/
+ */
+ mime_type = NULL;
+ if (gp_info.file.fields & GP_FILE_INFO_TYPE)
+ {
+ /* application/x-unknown is a bogus mime type return by some
+ * devices (such as Sandisk Sansa music players) - ignore it.
+ */
+ if (strcmp (gp_info.file.type, "application/x-unknown") != 0)
+ {
+ mime_type = g_strdup (gp_info.file.type);
+ }
+ }
+ if (mime_type == NULL)
+ mime_type = g_content_type_guess (name, NULL, 0, NULL);
+ if (mime_type == NULL)
+ mime_type = g_strdup ("application/octet-stream");
+ g_file_info_set_content_type (info, mime_type);
+
+ /* assume that all JPG files, and only all JPG files, has a preview file */
+ if (strcmp (mime_type, "image/jpg") == 0 ||
+ strcmp (mime_type, "image/jpeg") == 0)
+ {
+ char *icon_id;
+ GIcon *icon;
+ GMountSpec *mount_spec;
+
+ mount_spec = g_vfs_backend_get_mount_spec (G_VFS_BACKEND (gphoto2_backend));
+ icon_id = g_strdup_printf ("preview:%s/%s", dir + strlen (gphoto2_backend->ignore_prefix), name);
+ icon = g_vfs_icon_new (mount_spec,
+ icon_id);
+ g_file_info_set_attribute_object (info,
+ G_FILE_ATTRIBUTE_PREVIEW_ICON,
+ G_OBJECT (icon));
+ g_object_unref (icon);
+ g_free (icon_id);
+ }
+
+ icon = g_content_type_get_icon (mime_type);
+ DEBUG (" got icon %p for mime_type '%s'", icon, mime_type);
+ if (icon != NULL)
+ {
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+ g_free (mime_type);
+
+ if (gp_info.file.fields & GP_FILE_INFO_MTIME)
+ mtime.tv_sec = gp_info.file.mtime;
+ else
+ mtime.tv_sec = 0;
+ mtime.tv_usec = 0;
+ g_file_info_set_modification_time (info, &mtime);
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, gphoto2_backend->can_write);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, gphoto2_backend->can_write);
+ g_file_info_set_is_hidden (info, name != NULL && name[0] == '.');
+
+ if (gp_info.file.fields & GP_FILE_INFO_PERMISSIONS) {
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ gp_info.file.permissions & GP_FILE_PERM_DELETE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE,
+ gp_info.file.permissions & GP_FILE_PERM_DELETE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME,
+ gp_info.file.permissions & GP_FILE_PERM_DELETE);
+ }
+
+ ret = TRUE;
+ DEBUG (" Generating info (file) for '%s'", full_path);
+
+ add_to_cache:
+ /* add this sucker to the cache */
+ if (ret == TRUE)
+ {
+#ifndef DEBUG_NO_CACHING
+ cached_info = g_file_info_dup (info);
+ DEBUG (" Storing cached info %p for '%s'", cached_info, full_path);
+ g_mutex_lock (gphoto2_backend->lock);
+ g_hash_table_insert (gphoto2_backend->info_cache, g_strdup (full_path), cached_info);
+ g_mutex_unlock (gphoto2_backend->lock);
+#endif
+ }
+
+ out:
+ g_free (full_path);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+is_directory (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ GFileInfo *info;
+ gboolean ret;
+
+ ret = FALSE;
+
+ info = g_file_info_new ();
+ if (!file_get_info (gphoto2_backend, dir, name, info, NULL, FALSE))
+ goto out;
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ ret = TRUE;
+
+ out:
+ g_object_unref (info);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+is_regular (GVfsBackendGphoto2 *gphoto2_backend, const char *dir, const char *name)
+{
+ GFileInfo *info;
+ gboolean ret;
+
+ ret = FALSE;
+
+ info = g_file_info_new ();
+ if (!file_get_info (gphoto2_backend, dir, name, info, NULL, FALSE))
+ goto out;
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR)
+ ret = TRUE;
+
+ out:
+ g_object_unref (info);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+is_directory_empty (GVfsBackendGphoto2 *gphoto2_backend, const char *dir)
+{
+ CameraList *list;
+ gboolean ret;
+ int rc;
+ int num_dirs;
+ int num_files;
+
+ DEBUG ("is_directory_empty begin (%s)", dir);
+
+ /* TODO: use cache */
+
+ ret = FALSE;
+ num_dirs = 0;
+ num_files = 0;
+
+ gp_list_new (&list);
+ rc = gp_camera_folder_list_files (gphoto2_backend->camera,
+ dir,
+ list,
+ gphoto2_backend->context);
+ if (rc == 0)
+ num_files = gp_list_count (list);
+ gp_list_free (list);
+
+ if (num_files > 0)
+ goto out;
+
+ gp_list_new (&list);
+ rc = gp_camera_folder_list_folders (gphoto2_backend->camera,
+ dir,
+ list,
+ gphoto2_backend->context);
+ if (rc == 0)
+ num_dirs = gp_list_count (list);
+ gp_list_free (list);
+
+ if (num_dirs == 0 && num_files == 0)
+ ret = TRUE;
+
+ out:
+ DEBUG (" is_directory_empty (%s) -> %d", dir, ret);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* If we only have a single storage head, the gphoto2 volume monitor
+ * will not use activation roots into our mount. This is mainly to
+ * work around buggy devices where the basedir of the storage head
+ * changes on every camera initialization, e.g. the iPhone.
+ *
+ * So, if we have only one storage head, do use basedir of that
+ * head as ignore_prefix.
+ *
+ * See also update_cameras() in ggphoto2volumemonitor.c.
+ *
+ * This function needs to be called from do_mount().
+ */
+static gboolean
+ensure_ignore_prefix (GVfsBackendGphoto2 *gphoto2_backend, GVfsJob *job)
+{
+ gchar *prefix;
+ CameraStorageInformation *storage_info, *head;
+ int num_storage_info, i;
+
+ /* already set */
+ if (gphoto2_backend->ignore_prefix != NULL)
+ return TRUE;
+
+ prefix = NULL;
+
+ if (gp_camera_get_storageinfo (gphoto2_backend->camera,
+ &storage_info,
+ &num_storage_info,
+ gphoto2_backend->context) != 0)
+ goto out;
+
+ head = NULL;
+ for (i = 0; i < num_storage_info; i++)
+ {
+ /* Ignore storage with no capacity (see bug 570888) */
+ if ((storage_info[i].fields & GP_STORAGEINFO_MAXCAPACITY) &&
+ storage_info[i].capacitykbytes == 0)
+ continue;
+
+ /* Multiple heads, don't ignore */
+ if (head != NULL)
+ goto out;
+
+ head = &storage_info[i];
+ }
+
+ prefix = g_strdup_printf ("%s/", head->basedir);
+
+ out:
+
+ if (prefix == NULL)
+ gphoto2_backend->ignore_prefix = g_strdup ("/");
+ else
+ gphoto2_backend->ignore_prefix = prefix;
+
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ char *fuse_name;
+ char *display_name;
+ char *icon_name;
+ const char *host;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ GError *error = NULL;
+ GMountSpec *gphoto2_mount_spec;
+ int rc;
+ GPPortInfo info;
+ GPPortInfoList *il = NULL;
+ int n;
+ DBusError dbus_error;
+ CameraStorageInformation *storage_info;
+ int num_storage_info;
+
+ DEBUG ("do_mount %p", gphoto2_backend);
+
+ /* setup libhal */
+
+ dbus_error_init (&dbus_error);
+ gphoto2_backend->dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ release_device (gphoto2_backend);
+ dbus_error_free (&dbus_error);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot connect to the system bus"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ dbus_connection_set_exit_on_disconnect (gphoto2_backend->dbus_connection, FALSE);
+
+ gphoto2_backend->hal_ctx = libhal_ctx_new ();
+ if (gphoto2_backend->hal_ctx == NULL)
+ {
+ release_device (gphoto2_backend);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot create libhal context"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ _g_dbus_connection_integrate_with_main (gphoto2_backend->dbus_connection);
+ libhal_ctx_set_dbus_connection (gphoto2_backend->hal_ctx, gphoto2_backend->dbus_connection);
+
+ if (!libhal_ctx_init (gphoto2_backend->hal_ctx, &dbus_error))
+ {
+ release_device (gphoto2_backend);
+ dbus_error_free (&dbus_error);
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot initialize libhal"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ libhal_ctx_set_device_removed (gphoto2_backend->hal_ctx, _hal_device_removed);
+ libhal_ctx_set_user_data (gphoto2_backend->hal_ctx, gphoto2_backend);
+
+ /* setup gphoto2 */
+
+ host = g_mount_spec_get (mount_spec, "host");
+ DEBUG (" host='%s'", host);
+ if (host == NULL || strlen (host) < 3 || host[0] != '[' || host[strlen (host) - 1] != ']')
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No device specified"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ gphoto2_backend->gphoto2_port = g_strdup (host + 1);
+ gphoto2_backend->gphoto2_port[strlen (gphoto2_backend->gphoto2_port) - 1] = '\0';
+
+ DEBUG (" decoded host='%s'", gphoto2_backend->gphoto2_port);
+
+ find_udi_for_device (gphoto2_backend);
+
+ gphoto2_backend->context = gp_context_new ();
+ if (gphoto2_backend->context == NULL)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot create gphoto2 context"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ rc = gp_camera_new (&(gphoto2_backend->camera));
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error creating camera"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+
+ il = NULL;
+
+ rc = gp_port_info_list_new (&il);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error loading device information"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ rc = gp_port_info_list_load (il);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error loading device information"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ DEBUG (" gphoto2_port='%s'", gphoto2_backend->gphoto2_port);
+
+ n = gp_port_info_list_lookup_path (il, gphoto2_backend->gphoto2_port);
+ if (n == GP_ERROR_UNKNOWN_PORT)
+ {
+ error = get_error_from_gphoto2 (_("Error looking up device information"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ rc = gp_port_info_list_get_info (il, n, &info);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error getting device information"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ DEBUG (" '%s' '%s' '%s'", info.name, info.path, info.library_filename);
+
+ /* set port */
+ rc = gp_camera_set_port_info (gphoto2_backend->camera, info);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error setting up camera communications port"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+ gp_port_info_list_free(il);
+
+ rc = gp_camera_init (gphoto2_backend->camera, gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error initializing camera"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ if (!ensure_ignore_prefix (gphoto2_backend, G_VFS_JOB (job)))
+ {
+ release_device (gphoto2_backend);
+ return;
+ }
+
+ /* Translator: %s represents the device, e.g. usb:001,042 */
+ fuse_name = g_strdup_printf (_("gphoto2 mount on %s"), gphoto2_backend->gphoto2_port);
+ icon_name = compute_icon_name (gphoto2_backend);
+ display_name = compute_display_name (gphoto2_backend);
+ g_vfs_backend_set_stable_name (backend, fuse_name);
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_vfs_backend_set_icon_name (backend, icon_name);
+ g_free (display_name);
+ g_free (icon_name);
+ g_free (fuse_name);
+
+ gphoto2_backend->can_write = FALSE;
+ rc = gp_camera_get_storageinfo (gphoto2_backend->camera, &storage_info, &num_storage_info, gphoto2_backend->context);
+ if (rc == 0)
+ {
+ if (num_storage_info >= 1)
+ {
+ if (storage_info[0].fields & GP_STORAGEINFO_ACCESS && storage_info[0].access == GP_STORAGEINFO_AC_READWRITE)
+ {
+ gphoto2_backend->can_write = TRUE;
+ }
+ }
+ }
+ DEBUG (" can_write = %d", gphoto2_backend->can_write);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ gphoto2_backend->free_space = -1;
+
+ gphoto2_backend->lock = g_mutex_new ();
+
+ gphoto2_mount_spec = g_mount_spec_new ("gphoto2");
+ g_mount_spec_set (gphoto2_mount_spec, "host", host);
+ g_vfs_backend_set_mount_spec (backend, gphoto2_mount_spec);
+ g_mount_spec_unref (gphoto2_mount_spec);
+
+ gphoto2_backend->info_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ gphoto2_backend->dir_name_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) gp_list_unref);
+
+ gphoto2_backend->file_name_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) gp_list_unref);
+
+ DEBUG (" mounted %p", gphoto2_backend);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ const char *host;
+ GError *error = NULL;
+ GMountSpec *gphoto2_mount_spec;
+
+ DEBUG ("try_mount %p", backend);
+
+ /* TODO: Hmm.. apparently we have to set the mount spec in
+ * try_mount(); doing it in mount() do_won't work..
+ */
+ host = g_mount_spec_get (mount_spec, "host");
+ DEBUG (" host=%s", host);
+ if (host == NULL)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No camera specified"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return TRUE;
+ }
+
+ gphoto2_mount_spec = g_mount_spec_new ("gphoto2");
+ g_mount_spec_set (gphoto2_mount_spec, "host", host);
+ g_vfs_backend_set_mount_spec (backend, gphoto2_mount_spec);
+ g_mount_spec_unref (gphoto2_mount_spec);
+ return FALSE;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_unmount (GVfsBackend *backend,
+ GVfsJobUnmount *job)
+{
+ GError *error;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ int num_open_files;
+
+ num_open_files = gphoto2_backend->num_open_files_for_reading + g_list_length (gphoto2_backend->open_write_handles);
+
+ if (num_open_files > 0)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_BUSY,
+ ngettext("File system is busy: %d open file",
+ "File system is busy: %d open files",
+ num_open_files),
+ num_open_files);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ release_device (gphoto2_backend);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ DEBUG ("unmounted %p", backend);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+free_read_handle (ReadHandle *read_handle)
+{
+ if (read_handle->file != NULL)
+ {
+ gp_file_unref (read_handle->file);
+ }
+ g_free (read_handle);
+}
+
+static void
+do_open_for_read_real (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename,
+ gboolean get_preview)
+{
+ int rc;
+ GError *error;
+ ReadHandle *read_handle;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *dir;
+ char *name;
+
+ ensure_not_dirty (gphoto2_backend);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ if (is_directory (gphoto2_backend, dir, name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+ goto out;
+ }
+
+ if (!is_regular (gphoto2_backend, dir, name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file"));
+ goto out;
+ }
+
+ read_handle = g_new0 (ReadHandle, 1);
+ rc = gp_file_new (&read_handle->file);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error creating file object"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ free_read_handle (read_handle);
+ goto out;
+ }
+
+ rc = gp_camera_file_get (gphoto2_backend->camera,
+ dir,
+ name,
+ get_preview ? GP_FILE_TYPE_PREVIEW : GP_FILE_TYPE_NORMAL,
+ read_handle->file,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error getting file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ free_read_handle (read_handle);
+ goto out;
+ }
+
+ rc = gp_file_get_data_and_size (read_handle->file, &read_handle->data, &read_handle->size);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error getting data from file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ free_read_handle (read_handle);
+ goto out;
+ }
+
+ DEBUG (" data=%p size=%ld handle=%p", read_handle->data, read_handle->size, read_handle);
+
+ g_mutex_lock (gphoto2_backend->lock);
+ gphoto2_backend->num_open_files_for_reading++;
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ read_handle->cursor = 0;
+
+ g_vfs_job_open_for_read_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_read_set_handle (job, GINT_TO_POINTER (read_handle));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (name);
+ g_free (dir);
+}
+
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ DEBUG ("open_for_read (%s)", filename);
+
+ do_open_for_read_real (backend,
+ job,
+ filename,
+ FALSE);
+}
+
+static void
+do_open_icon_for_read (GVfsBackend *backend,
+ GVfsJobOpenIconForRead *job,
+ const char *icon_id)
+{
+ DEBUG ("open_icon_for_read (%s)", icon_id);
+
+ if (g_str_has_prefix (icon_id, "preview:"))
+ {
+ do_open_for_read_real (backend,
+ G_VFS_JOB_OPEN_FOR_READ (job),
+ icon_id + sizeof ("preview:") - 1,
+ TRUE);
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed icon identifier '%s'"),
+ icon_id);
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ //GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ gsize bytes_left;
+ gsize bytes_to_copy;
+
+ DEBUG ("do_read() %d @ %ld of %ld, handle=%p", bytes_requested, read_handle->cursor, read_handle->size, handle);
+
+ if (read_handle->cursor >= read_handle->size)
+ {
+ bytes_to_copy = 0;
+ goto out;
+ }
+
+ bytes_left = read_handle->size - read_handle->cursor;
+ if (bytes_requested > bytes_left)
+ bytes_to_copy = bytes_left;
+ else
+ bytes_to_copy = bytes_requested;
+
+ memcpy (buffer, read_handle->data + read_handle->cursor, bytes_to_copy);
+ read_handle->cursor += bytes_to_copy;
+
+ out:
+
+ g_vfs_job_read_set_size (job, bytes_to_copy);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ long new_offset;
+
+ DEBUG ("seek_on_read() offset=%d, type=%d, handle=%p", (int)offset, type, handle);
+
+ switch (type)
+ {
+ default:
+ case G_SEEK_SET:
+ new_offset = offset;
+ break;
+ case G_SEEK_CUR:
+ new_offset = read_handle->cursor + offset;
+ break;
+ case G_SEEK_END:
+ new_offset = read_handle->size + offset;
+ break;
+ }
+
+ if (new_offset < 0 || new_offset > read_handle->size)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Error seeking in stream on camera %s"), gphoto2_backend->gphoto2_port);
+ }
+ else
+ {
+ read_handle->cursor = new_offset;
+ g_vfs_job_seek_read_set_offset (job, offset);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* cannot be async because we unref the CameraFile */
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ ReadHandle *read_handle = (ReadHandle *) handle;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+
+ DEBUG ("close_read() handle=%p", handle);
+
+ free_read_handle (read_handle);
+
+ g_mutex_lock (gphoto2_backend->lock);
+ gphoto2_backend->num_open_files_for_reading--;
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ GError *error;
+ char *dir;
+ char *name;
+
+ DEBUG ("query_info (%s)", filename);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ error = NULL;
+ if (!file_get_info (gphoto2_backend, dir, name, info, &error, FALSE))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ g_free (name);
+ g_free (dir);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *dir;
+ char *name;
+ gboolean ret;
+
+ DEBUG ("try_query_info (%s)", filename);
+
+ ret = FALSE;
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ if (!file_get_info (gphoto2_backend, dir, name, info, NULL, TRUE))
+ {
+ DEBUG (" BUU no info from cache for try_query_info (%s)", filename);
+ goto out;
+ }
+ DEBUG (" YAY got info from cache for try_query_info (%s)", filename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ ret = TRUE;
+
+ out:
+ g_free (name);
+ g_free (dir);
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *given_filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ GFileInfo *info;
+ GList *l;
+ GError *error;
+ CameraList *list;
+ int n;
+ int rc;
+ char *filename;
+ gboolean using_cached_dir_list;
+ gboolean using_cached_file_list;
+ char *as_dir;
+ char *as_name;
+
+ l = NULL;
+ using_cached_dir_list = FALSE;
+ using_cached_file_list = FALSE;
+
+ filename = add_ignore_prefix (gphoto2_backend, given_filename);
+ DEBUG ("enumerate (%s)", given_filename);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, given_filename, &as_dir, &as_name);
+ if (!is_directory (gphoto2_backend, as_dir, as_name))
+ {
+ if (is_regular (gphoto2_backend, as_dir, as_name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("Not a directory"));
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ }
+ g_free (as_dir);
+ g_free (as_name);
+ return;
+ }
+ g_free (as_dir);
+ g_free (as_name);
+
+ /* first, list the folders */
+ g_mutex_lock (gphoto2_backend->lock);
+ list = g_hash_table_lookup (gphoto2_backend->dir_name_cache, filename);
+ if (list == NULL)
+ {
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ ensure_not_dirty (gphoto2_backend);
+
+ DEBUG (" Generating dir list for dir '%s'", filename);
+
+ gp_list_new (&list);
+ rc = gp_camera_folder_list_folders (gphoto2_backend->camera,
+ filename,
+ list,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Failed to get folder list"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_free (filename);
+ return;
+ }
+ }
+ else
+ {
+ DEBUG (" Using cached dir list for dir '%s'", filename);
+ using_cached_dir_list = TRUE;
+ gp_list_ref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ }
+ for (n = 0; n < gp_list_count (list); n++)
+ {
+ const char *name;
+
+ gp_list_get_name (list, n, &name);
+ DEBUG (" enum folder '%s'", name);
+ info = g_file_info_new ();
+ error = NULL;
+ if (!file_get_info (gphoto2_backend, filename, name, info, &error, FALSE))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+ gp_list_free (list);
+ return;
+ }
+ l = g_list_append (l, info);
+ }
+ if (!using_cached_dir_list)
+ {
+#ifndef DEBUG_NO_CACHING
+ g_mutex_lock (gphoto2_backend->lock);
+ g_hash_table_insert (gphoto2_backend->dir_name_cache, g_strdup (filename), list);
+ g_mutex_unlock (gphoto2_backend->lock);
+#endif
+ }
+ else
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ }
+
+
+ /* then list the files in each folder */
+ g_mutex_lock (gphoto2_backend->lock);
+ list = g_hash_table_lookup (gphoto2_backend->file_name_cache, filename);
+ if (list == NULL)
+ {
+ g_mutex_unlock (gphoto2_backend->lock);
+ ensure_not_dirty (gphoto2_backend);
+
+ DEBUG (" Generating file list for dir '%s'", filename);
+
+ gp_list_new (&list);
+ rc = gp_camera_folder_list_files (gphoto2_backend->camera,
+ filename,
+ list,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Failed to get file list"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_free (filename);
+ return;
+ }
+ }
+ else
+ {
+ DEBUG (" Using cached file list for dir '%s'", filename);
+ using_cached_file_list = TRUE;
+ gp_list_ref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ }
+ for (n = 0; n < gp_list_count (list); n++)
+ {
+ const char *name;
+
+ gp_list_get_name (list, n, &name);
+ DEBUG (" enum file '%s'", name);
+
+ info = g_file_info_new ();
+ error = NULL;
+ if (!file_get_info (gphoto2_backend, filename, name, info, &error, FALSE))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+ gp_list_free (list);
+ return;
+ }
+ l = g_list_append (l, info);
+ }
+ if (!using_cached_file_list)
+ {
+#ifndef DEBUG_NO_CACHING
+ g_mutex_lock (gphoto2_backend->lock);
+ g_hash_table_insert (gphoto2_backend->file_name_cache, g_strdup (filename), list);
+ g_mutex_unlock (gphoto2_backend->lock);
+#endif
+ }
+ else
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ }
+
+ /* and we're done */
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_vfs_job_enumerate_add_infos (job, l);
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+ g_vfs_job_enumerate_done (job);
+
+ g_free (filename);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *given_filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ GFileInfo *info;
+ GList *l;
+ GError *error;
+ CameraList *list;
+ int n;
+ char *filename;
+ const char *name;
+
+ l = NULL;
+
+ filename = add_ignore_prefix (gphoto2_backend, given_filename);
+ DEBUG ("try_enumerate (%s)", given_filename);
+
+ /* first, list the folders */
+ g_mutex_lock (gphoto2_backend->lock);
+ list = g_hash_table_lookup (gphoto2_backend->dir_name_cache, filename);
+ if (list == NULL)
+ {
+ g_mutex_unlock (gphoto2_backend->lock);
+ goto error_not_cached;
+ }
+ gp_list_ref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ for (n = 0; n < gp_list_count (list); n++)
+ {
+ gp_list_get_name (list, n, &name);
+ DEBUG (" try_enum folder '%s'", name);
+ info = g_file_info_new ();
+ if (!file_get_info (gphoto2_backend, filename, name, info, &error, TRUE))
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ goto error_not_cached;
+ }
+ l = g_list_append (l, info);
+ }
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ /* then list the files in each folder */
+ g_mutex_lock (gphoto2_backend->lock);
+ list = g_hash_table_lookup (gphoto2_backend->file_name_cache, filename);
+ if (list == NULL)
+ {
+ g_mutex_unlock (gphoto2_backend->lock);
+ goto error_not_cached;
+ }
+ gp_list_ref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ for (n = 0; n < gp_list_count (list); n++)
+ {
+ gp_list_get_name (list, n, &name);
+ DEBUG (" try_enum file '%s'", name);
+
+ info = g_file_info_new ();
+ if (!file_get_info (gphoto2_backend, filename, name, info, &error, TRUE))
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+ goto error_not_cached;
+ }
+ l = g_list_append (l, info);
+ }
+ g_mutex_lock (gphoto2_backend->lock);
+ gp_list_unref (list);
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ /* and we're done */
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_vfs_job_enumerate_add_infos (job, l);
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+ g_vfs_job_enumerate_done (job);
+
+ g_free (filename);
+ DEBUG (" YAY got info from cache for try_enumerate (%s)", given_filename);
+ return TRUE;
+
+ error_not_cached:
+ g_list_foreach (l, (GFunc) g_object_unref, NULL);
+ g_list_free (l);
+
+ g_free (filename);
+ DEBUG (" BUU no info from cache for try_enumerate (%s)", given_filename);
+ return FALSE;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ int rc;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ CameraStorageInformation *storage_info;
+ int num_storage_info;
+
+ DEBUG ("query_fs_info (%s)", filename);
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "gphoto2");
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, !gphoto2_backend->can_write);
+
+ rc = gp_camera_get_storageinfo (gphoto2_backend->camera, &storage_info, &num_storage_info, gphoto2_backend->context);
+ if (rc == 0)
+ {
+ if (num_storage_info >= 1)
+ {
+ /* for now we only support a single storage head */
+ if (storage_info[0].fields & GP_STORAGEINFO_MAXCAPACITY)
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gphoto2_backend->capacity = storage_info[0].capacitykbytes * 1024;
+ g_mutex_unlock (gphoto2_backend->lock);
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,
+ (guint64) gphoto2_backend->capacity);
+ }
+
+ if (storage_info[0].fields & GP_STORAGEINFO_FREESPACEKBYTES)
+ {
+ g_mutex_lock (gphoto2_backend->lock);
+ gphoto2_backend->free_space = storage_info[0].freekbytes * 1024;
+ g_mutex_unlock (gphoto2_backend->lock);
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
+ (guint64) gphoto2_backend->free_space);
+ }
+ }
+ DEBUG (" got %d storage_info objects", num_storage_info);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static gboolean
+try_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ gboolean ret;
+ gint64 free_space;
+ gint64 capacity;
+
+ DEBUG ("try_query_fs_info (%s)", filename);
+
+ ret = FALSE;
+
+ g_mutex_lock (gphoto2_backend->lock);
+ free_space = gphoto2_backend->free_space;
+ capacity = gphoto2_backend->capacity;
+ g_mutex_unlock (gphoto2_backend->lock);
+
+ if (free_space == -1 || capacity == -1)
+ {
+ DEBUG (" BUU no info from cache for try_query_fs_info (%s)", filename);
+ goto out;
+ }
+ DEBUG (" YAY got info from cache for try_query_fs_info (%s)", filename);
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "gphoto2");
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, !gphoto2_backend->can_write);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, (guint64) capacity);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, (guint64) free_space);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *name;
+ char *dir;
+ int rc;
+ GError *error;
+
+ DEBUG ("make_directory (%s)", filename);
+
+ ensure_not_dirty (gphoto2_backend);
+
+ dir = NULL;
+ name = NULL;
+ error = NULL;
+
+ if (!gphoto2_backend->can_write)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+ goto out;
+ }
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ rc = gp_camera_folder_make_dir (gphoto2_backend->camera,
+ dir,
+ name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error creating directory"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+
+ caches_invalidate_dir (gphoto2_backend, dir);
+ caches_invalidate_free_space (gphoto2_backend);
+ monitors_emit_created (gphoto2_backend, dir, name);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (dir);
+ g_free (name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static int
+do_slow_file_rename_in_same_dir (GVfsBackendGphoto2 *gphoto2_backend,
+ const char *dir,
+ const char *name,
+ const char *new_name,
+ gboolean allow_overwrite)
+{
+ int rc;
+ CameraFile *file;
+ CameraFile *file_dest;
+ const char *data;
+ unsigned long int size;
+
+ file = NULL;
+ file_dest = NULL;
+
+ DEBUG ("do_slow_file_rename_in_same_dir() '%s' '%s' -> '%s'", dir, name, new_name);
+
+ rc = gp_file_new (&file);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_camera_file_get (gphoto2_backend->camera,
+ dir,
+ name,
+ GP_FILE_TYPE_NORMAL,
+ file,
+ gphoto2_backend->context);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_file_get_data_and_size (file, &data, &size);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_file_new (&file_dest);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_file_copy (file_dest, file);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_file_set_name (file_dest, new_name);
+ if (rc != 0)
+ goto out;
+
+ if (allow_overwrite)
+ {
+ gp_camera_file_delete (gphoto2_backend->camera,
+ dir,
+ new_name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ DEBUG (" file delete failed as part of slow rename rc=%d", rc);
+ goto out;
+ }
+ }
+
+ rc = gp_camera_folder_put_file (gphoto2_backend->camera, dir, file_dest, gphoto2_backend->context);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_camera_file_delete (gphoto2_backend->camera,
+ dir,
+ name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ /* at least try to clean up the newly created file... */
+ gp_camera_file_delete (gphoto2_backend->camera,
+ dir,
+ new_name,
+ gphoto2_backend->context);
+ goto out;
+ }
+
+ out:
+ if (file != NULL)
+ gp_file_unref (file);
+ if (file_dest != NULL)
+ gp_file_unref (file_dest);
+ return rc;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static int
+do_file_rename_in_same_dir (GVfsBackendGphoto2 *gphoto2_backend,
+ const char *dir,
+ const char *name,
+ const char *new_name,
+ gboolean allow_overwrite)
+{
+ /* TODO: The libgphoto2 API speaks of just using
+ * gp_camera_file_set_info() to achieve this. However this
+ * fails on the devices that I own. So fall back to the slow
+ * method for now. Patches welcome for someone with a device
+ * where the above mentioned trick works.
+ */
+ return do_slow_file_rename_in_same_dir (gphoto2_backend, dir, name, new_name, allow_overwrite);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static int
+do_dir_rename_in_same_dir (GVfsBackendGphoto2 *gphoto2_backend,
+ const char *dir,
+ const char *name,
+ const char *new_name)
+{
+ int rc;
+ char *dir_name;
+
+ dir_name = g_build_filename (dir, name, NULL);
+
+ DEBUG ("do_dir_rename_in_same_dir() '%s' '%s' -> '%s' ('%s')", dir, name, new_name, dir_name);
+
+ /* TODO: Support non-empty folders by recursively renaming stuff.
+ * Or that might be too dangerous as it's not exactly atomic.
+ * And renaming files may be slow; see do_file_rename_in_same_dir() above.
+ */
+ if (is_directory_empty (gphoto2_backend, dir_name))
+ {
+ rc = gp_camera_folder_make_dir (gphoto2_backend->camera,
+ dir,
+ new_name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ goto out;
+
+ rc = gp_camera_folder_remove_dir (gphoto2_backend->camera,
+ dir,
+ name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ goto out;
+ }
+ else
+ {
+ rc = GP_ERROR_NOT_SUPPORTED;
+ }
+
+ out:
+ g_free (dir_name);
+ return rc;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *name;
+ char *dir;
+ int rc;
+ char *dir_name;
+ GError *error;
+ char *new_name;
+
+ ensure_not_dirty (gphoto2_backend);
+
+ DEBUG ("set_display_name() '%s' -> '%s'", filename, display_name);
+
+ dir = NULL;
+ name = NULL;
+ dir_name = NULL;
+ new_name = NULL;
+
+ if (!gphoto2_backend->can_write)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+ goto out;
+ }
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ /* refuse is desired name is already taken */
+ if (is_directory (gphoto2_backend, dir, display_name) ||
+ is_regular (gphoto2_backend, dir, display_name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Name already exists"));
+ goto out;
+ }
+
+ /* ensure name is not too long - otherwise it might screw up enumerating
+ * the folder on some devices
+ */
+ if (strlen (display_name) > 63)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("New name too long"));
+ goto out;
+ }
+
+ if (is_directory (gphoto2_backend, dir, name))
+ {
+ /* dir renaming */
+ rc = do_dir_rename_in_same_dir (gphoto2_backend, dir, name, display_name);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error renaming dir"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ caches_invalidate_file (gphoto2_backend, dir, name);
+ }
+ else
+ {
+ /* file renaming */
+ rc = do_file_rename_in_same_dir (gphoto2_backend, dir, name, display_name, FALSE);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error renaming file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ caches_invalidate_file (gphoto2_backend, dir, name);
+ }
+
+
+ /* emit on monitor */
+ monitors_emit_deleted (gphoto2_backend, dir, name);
+ monitors_emit_created (gphoto2_backend, dir, display_name);
+
+ new_name = g_build_filename (dir + strlen (gphoto2_backend->ignore_prefix), display_name, NULL);
+ g_vfs_job_set_display_name_set_new_path (job, new_name);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (dir);
+ g_free (name);
+ g_free (dir_name);
+ g_free (new_name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *name;
+ char *dir;
+ int rc;
+ GError *error;
+ char *dir_name;
+
+ ensure_not_dirty (gphoto2_backend);
+
+ DEBUG ("delete() '%s'", filename);
+
+ dir = NULL;
+ name = NULL;
+ dir_name = NULL;
+
+ if (!gphoto2_backend->can_write)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+ goto out;
+ }
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ if (is_directory (gphoto2_backend, dir, name))
+ {
+ dir_name = add_ignore_prefix (gphoto2_backend, filename);
+ if (!is_directory_empty (gphoto2_backend, dir_name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_EMPTY,
+ _("Directory '%s' is not empty"), filename);
+ goto out;
+ }
+ else
+ {
+ rc = gp_camera_folder_remove_dir (gphoto2_backend->camera,
+ dir,
+ name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error deleting directory"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ caches_invalidate_file (gphoto2_backend, dir, name);
+ caches_invalidate_free_space (gphoto2_backend);
+ monitors_emit_deleted (gphoto2_backend, dir, name);
+ }
+ }
+ else
+ {
+ if (!is_regular (gphoto2_backend, dir, name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+ goto out;
+ }
+
+ rc = gp_camera_file_delete (gphoto2_backend->camera,
+ dir,
+ name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error deleting file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+
+ caches_invalidate_file (gphoto2_backend, dir, name);
+ caches_invalidate_free_space (gphoto2_backend);
+ monitors_emit_deleted (gphoto2_backend, dir, name);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (dir);
+ g_free (name);
+ g_free (dir_name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_create_internal (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags,
+ gboolean job_is_replace,
+ gboolean job_is_append_to)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ WriteHandle *handle;
+ char *dir;
+ char *name;
+
+ ensure_not_dirty (gphoto2_backend);
+
+ dir = NULL;
+ name = NULL;
+
+ if (!gphoto2_backend->can_write)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported"));
+ goto out;
+ }
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ if (is_directory (gphoto2_backend, dir, name))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't write to directory"));
+ goto out;
+ }
+
+ /* unless we're replacing or appending.. error out if file already exists */
+ if (is_regular (gphoto2_backend, dir, name))
+ {
+ if (! (job_is_replace || job_is_append_to))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("File exists"));
+ goto out;
+ }
+ }
+ else
+ {
+ if (job_is_replace || job_is_append_to)
+ {
+ /* so we're not really replacing or appending; dont fail these
+ * operations; just turn them into create instead...
+ */
+ job_is_replace = FALSE;
+ job_is_append_to = FALSE;
+ }
+ }
+
+ handle = g_new0 (WriteHandle, 1);
+ handle->filename = g_strdup (filename);
+ handle->dir = g_strdup (dir);
+ handle->name = g_strdup (name);
+ handle->job_is_replace = job_is_replace;
+ handle->job_is_append_to = job_is_append_to;
+ handle->is_dirty = TRUE;
+
+ /* if we're appending to a file read in all of the file to memory */
+ if (job_is_append_to)
+ {
+ int rc;
+ GError *error;
+ CameraFile *file;
+ const char *data;
+ unsigned long int size;
+
+ rc = gp_file_new (&file);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Cannot allocate new file to append to"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ write_handle_free (handle);
+ goto out;
+ }
+
+ rc = gp_camera_file_get (gphoto2_backend->camera,
+ dir,
+ name,
+ GP_FILE_TYPE_NORMAL,
+ file,
+ gphoto2_backend->context);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Cannot read file to append to"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ write_handle_free (handle);
+ gp_file_unref (file);
+ goto out;
+ }
+
+ rc = gp_file_get_data_and_size (file, &data, &size);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Cannot get data of file to append to"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ write_handle_free (handle);
+ gp_file_unref (file);
+ goto out;
+ }
+
+ handle->data = g_malloc (size + WRITE_INCREMENT);
+ handle->allocated_size = size + WRITE_INCREMENT;
+ handle->size = size;
+ handle->cursor = size;
+ memcpy (handle->data, data, size);
+ gp_file_unref (file);
+
+ }
+ else
+ {
+ handle->data = g_malloc (WRITE_INCREMENT);
+ handle->allocated_size = WRITE_INCREMENT;
+ }
+
+ g_vfs_job_open_for_write_set_handle (job, handle);
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
+
+ gphoto2_backend->open_write_handles = g_list_prepend (gphoto2_backend->open_write_handles, handle);
+
+ DEBUG (" handle=%p", handle);
+
+ /* make sure we invalidate the dir and the file */
+ caches_invalidate_file (gphoto2_backend, dir, name);
+
+ /* emit on the monitor - hopefully some client won't need info
+ * about this (to avoid committing dirty bits midwrite) before
+ * the write is done...
+ */
+ if (job_is_replace || job_is_append_to)
+ monitors_emit_changed (gphoto2_backend, dir, name);
+ else
+ monitors_emit_created (gphoto2_backend, dir, name);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (dir);
+ g_free (name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ DEBUG ("create() '%s' flags=0x%04x", filename, flags);
+
+ return do_create_internal (backend, job, filename, flags, FALSE, FALSE);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *dir;
+ char *name;
+
+ DEBUG ("replace() '%s' etag='%s' make_backup=%d flags=0x%04x", filename, etag, make_backup, flags);
+
+ dir = NULL;
+ name = NULL;
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ /* write a new file
+ * - will delete the existing one when done in do_close_write()
+ */
+ do_create_internal (backend, job, filename, flags, TRUE, FALSE);
+
+ g_free (dir);
+ g_free (name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *dir;
+ char *name;
+
+ DEBUG ("append_to() '%s' flags=0x%04x", filename, flags);
+
+ dir = NULL;
+ name = NULL;
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ /* write a new file
+ * - will read existing data in do_create_internal
+ * - will delete the existing one when done in do_close_write()
+ */
+ do_create_internal (backend, job, filename, flags, FALSE, TRUE);
+
+ g_free (dir);
+ g_free (name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ WriteHandle *handle = _handle;
+
+ DEBUG ("write() %p, '%s', %d bytes", handle, handle->filename, buffer_size);
+
+ /* ensure we have enough room */
+ if (handle->cursor + buffer_size > handle->allocated_size)
+ {
+ unsigned long int new_allocated_size;
+ new_allocated_size = ((handle->cursor + buffer_size) / WRITE_INCREMENT + 1) * WRITE_INCREMENT;
+ handle->data = g_realloc (handle->data, new_allocated_size);
+ handle->allocated_size = new_allocated_size;
+ DEBUG (" allocated_size is now %ld bytes)", handle->allocated_size);
+ }
+
+
+ memcpy (handle->data + handle->cursor, buffer, buffer_size);
+ handle->cursor += buffer_size;
+
+ if (handle->cursor > handle->size)
+ handle->size = handle->cursor;
+
+ /* this will make us dirty */
+ handle->is_dirty = TRUE;
+
+ g_vfs_job_write_set_written_size (job, buffer_size);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_seek_on_write (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ WriteHandle *write_handle = handle;
+ long new_offset;
+
+ DEBUG ("seek_on_write() %p '%s' offset=%d type=%d cursor=%ld size=%ld", write_handle, write_handle->filename, (int)offset, type, write_handle->cursor, write_handle->size);
+
+ switch (type)
+ {
+ default:
+ case G_SEEK_SET:
+ new_offset = offset;
+ break;
+ case G_SEEK_CUR:
+ new_offset = write_handle->cursor + offset;
+ break;
+ case G_SEEK_END:
+ new_offset = write_handle->size + offset;
+ break;
+ }
+
+ if (new_offset < 0 || new_offset > write_handle->size)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Error seeking in stream on camera %s"), gphoto2_backend->gphoto2_port);
+ }
+ else
+ {
+ write_handle->cursor = new_offset;
+ g_vfs_job_seek_write_set_offset (job, offset);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+/* this functions updates the device with the data currently in write_handle */
+static int
+commit_write_handle (GVfsBackendGphoto2 *gphoto2_backend, WriteHandle *write_handle)
+{
+ int rc;
+ CameraFile *file;
+
+ DEBUG ("commit_write_handle() '%s' of size %ld", write_handle->filename, write_handle->size);
+
+ /* no need to write as we're not dirty */
+ if (!write_handle->is_dirty)
+ {
+ DEBUG (" not dirty => not writing");
+ return 0;
+ }
+
+ if (write_handle->delete_before ||
+ (write_handle->job_is_replace || write_handle->job_is_append_to))
+ {
+ /* OK, so this is not atomic. But there's no way we can make it
+ * atomic until rename works properly - see comments in
+ * do_set_display_name() and why have do_slow_rename()...
+ *
+ * So first delete the existing file...
+ */
+ rc = gp_camera_file_delete (gphoto2_backend->camera,
+ write_handle->dir,
+ write_handle->name,
+ gphoto2_backend->context);
+ if (rc != 0)
+ goto out;
+
+ DEBUG (" deleted '%s' '%s' for delete_before=%d, job_is_replace=%d, job_is_append_to=%d",
+ write_handle->dir, write_handle->name,
+ write_handle->delete_before, write_handle->job_is_replace, write_handle->job_is_append_to);
+ }
+
+ rc = gp_file_new (&file);
+ if (rc != 0)
+ goto out;
+
+ gp_file_set_type (file, GP_FILE_TYPE_NORMAL);
+ gp_file_set_name (file, write_handle->name);
+ gp_file_set_mtime (file, time (NULL));
+ gp_file_set_data_and_size (file,
+ dup_for_gphoto2 (write_handle->data, write_handle->size),
+ write_handle->size);
+
+ rc = gp_camera_folder_put_file (gphoto2_backend->camera, write_handle->dir, file, gphoto2_backend->context);
+ if (rc != 0)
+ {
+ gp_file_unref (file);
+ goto out;
+ }
+
+ DEBUG (" successfully wrote '%s' of %ld bytes", write_handle->filename, write_handle->size);
+ monitors_emit_changed (gphoto2_backend, write_handle->dir, write_handle->name);
+
+ gp_file_unref (file);
+
+ out:
+ write_handle->is_dirty = FALSE;
+ write_handle->delete_before = TRUE;
+
+ caches_invalidate_file (gphoto2_backend, write_handle->dir, write_handle->name);
+ caches_invalidate_free_space (gphoto2_backend);
+
+ return rc;
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ WriteHandle *write_handle = handle;
+ GError *error;
+ int rc;
+
+ DEBUG ("close_write() %p '%s' %ld bytes total", write_handle, write_handle->filename, write_handle->size);
+
+ rc = commit_write_handle (gphoto2_backend, write_handle);
+ if (rc != 0)
+ {
+ error = get_error_from_gphoto2 (_("Error writing file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+
+ monitors_emit_changed (gphoto2_backend, write_handle->dir, write_handle->name);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ write_handle_free (write_handle);
+ gphoto2_backend->open_write_handles = g_list_remove (gphoto2_backend->open_write_handles, write_handle);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+do_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ char *src_dir;
+ char *src_name;
+ char *dst_dir;
+ char *dst_name;
+ int rc;
+ GError *error;
+ gboolean mv_dir;
+
+ DEBUG ("move() '%s' -> '%s' %04x)", source, destination, flags);
+
+ ensure_not_dirty (gphoto2_backend);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, source, &src_dir, &src_name);
+ split_filename_with_ignore_prefix (gphoto2_backend, destination, &dst_dir, &dst_name);
+
+ /* this is an limited implementation that can only move files / folders in the same directory */
+ if (strcmp (src_dir, dst_dir) != 0)
+ {
+ DEBUG (" not supported (not same directory)");
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported (not same directory)"));
+ goto out;
+ }
+
+ mv_dir = FALSE;
+ if (is_directory (gphoto2_backend, src_dir, src_name))
+ {
+ if (is_directory (gphoto2_backend, dst_dir, dst_name))
+ {
+ DEBUG (" not supported (src is dir; dst is dir)");
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported (src is dir, dst is dir)"));
+ goto out;
+ }
+ else if (is_regular (gphoto2_backend, dst_dir, dst_name))
+ {
+ DEBUG (" not supported (src is dir; dst is existing file)");
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported (src is dir, dst is existing file)"));
+ goto out;
+ }
+ mv_dir = TRUE;
+ }
+ else
+ {
+ if (is_directory (gphoto2_backend, dst_dir, dst_name))
+ {
+ DEBUG (" not supported (src is file; dst is dir)");
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Not supported (src is file, dst is dir)"));
+ goto out;
+ }
+ }
+
+ /* ensure name is not too long - otherwise it might screw up enumerating
+ * the folder on some devices
+ */
+ if (strlen (dst_name) > 63)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("New name too long"));
+ goto out;
+ }
+
+ if (mv_dir)
+ {
+ DEBUG (" renaming dir");
+ rc = do_dir_rename_in_same_dir (gphoto2_backend, src_dir, src_name, dst_name);
+ if (rc != 0)
+ {
+ DEBUG (" error renaming dir");
+ error = get_error_from_gphoto2 (_("Error renaming dir"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ }
+ else
+ {
+ DEBUG (" renaming file");
+ rc = do_file_rename_in_same_dir (gphoto2_backend, src_dir, src_name, dst_name, flags & G_FILE_COPY_OVERWRITE);
+ if (rc != 0)
+ {
+ DEBUG (" error renaming file");
+ error = get_error_from_gphoto2 (_("Error renaming file"), rc);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
+ }
+
+ caches_invalidate_file (gphoto2_backend, src_dir, src_name);
+ monitors_emit_deleted (gphoto2_backend, src_dir, src_name);
+ monitors_emit_created (gphoto2_backend, src_dir, dst_name);
+
+ DEBUG (" success");
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ g_free (src_dir);
+ g_free (src_name);
+ g_free (dst_dir);
+ g_free (dst_name);
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+vfs_dir_monitor_destroyed (gpointer user_data, GObject *where_the_object_was)
+{
+ GList *l;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (user_data);
+
+ DEBUG ("vfs_dir_monitor_destroyed()");
+
+ for (l = gphoto2_backend->dir_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ if (G_OBJECT (proxy->vfs_monitor) == where_the_object_was)
+ {
+ gphoto2_backend->dir_monitor_proxies = g_list_remove (gphoto2_backend->dir_monitor_proxies, proxy);
+ DEBUG (" Removed dead dir monitor for '%s'", proxy->path);
+ monitor_proxy_free (proxy);
+ break;
+ }
+ }
+}
+
+static void
+do_create_dir_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ char *dir;
+ char *name;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ MonitorProxy *proxy;
+
+ DEBUG ("create_dir_monitor (%s)", filename);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ proxy = g_new0 (MonitorProxy, 1);
+ proxy->path = add_ignore_prefix (gphoto2_backend, filename);
+ proxy->vfs_monitor = g_vfs_monitor_new (backend);
+
+ gphoto2_backend->dir_monitor_proxies = g_list_prepend (gphoto2_backend->dir_monitor_proxies, proxy);
+
+ g_vfs_job_create_monitor_set_monitor (job, proxy->vfs_monitor);
+ g_object_weak_ref (G_OBJECT (proxy->vfs_monitor), vfs_dir_monitor_destroyed, gphoto2_backend);
+ g_object_unref (proxy->vfs_monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+vfs_file_monitor_destroyed (gpointer user_data, GObject *where_the_object_was)
+{
+ GList *l;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (user_data);
+
+ DEBUG ("vfs_file_monitor_destroyed()");
+
+ for (l = gphoto2_backend->file_monitor_proxies; l != NULL; l = l->next)
+ {
+ MonitorProxy *proxy = l->data;
+ if (G_OBJECT (proxy->vfs_monitor) == where_the_object_was)
+ {
+ gphoto2_backend->dir_monitor_proxies = g_list_remove (gphoto2_backend->dir_monitor_proxies, proxy);
+ DEBUG (" Removed dead file monitor for '%s'", proxy->path);
+ monitor_proxy_free (proxy);
+ break;
+ }
+ }
+}
+
+static void
+do_create_file_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ char *dir;
+ char *name;
+ GVfsBackendGphoto2 *gphoto2_backend = G_VFS_BACKEND_GPHOTO2 (backend);
+ MonitorProxy *proxy;
+
+ DEBUG ("create_file_monitor (%s)", filename);
+
+ split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name);
+
+ proxy = g_new0 (MonitorProxy, 1);
+ proxy->path = add_ignore_prefix (gphoto2_backend, filename);
+ proxy->vfs_monitor = g_vfs_monitor_new (backend);
+
+ gphoto2_backend->file_monitor_proxies = g_list_prepend (gphoto2_backend->file_monitor_proxies, proxy);
+
+ g_vfs_job_create_monitor_set_monitor (job, proxy->vfs_monitor);
+ g_object_weak_ref (G_OBJECT (proxy->vfs_monitor), vfs_file_monitor_destroyed, gphoto2_backend);
+ g_object_unref (proxy->vfs_monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* ------------------------------------------------------------------------------------------------- */
+
+static void
+g_vfs_backend_gphoto2_class_init (GVfsBackendGphoto2Class *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_gphoto2_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->mount = do_mount;
+ backend_class->unmount = do_unmount;
+ backend_class->open_icon_for_read = do_open_icon_for_read;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->try_read = try_read;
+ backend_class->try_seek_on_read = try_seek_on_read;
+ backend_class->close_read = do_close_read;
+ backend_class->query_info = do_query_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->query_fs_info = do_query_fs_info;
+ backend_class->make_directory = do_make_directory;
+ backend_class->set_display_name = do_set_display_name;
+ backend_class->delete = do_delete;
+ backend_class->create = do_create;
+ backend_class->replace = do_replace;
+ backend_class->append_to = do_append_to;
+ backend_class->write = do_write;
+ backend_class->close_write = do_close_write;
+ backend_class->seek_on_write = do_seek_on_write;
+ backend_class->move = do_move;
+ backend_class->create_dir_monitor = do_create_dir_monitor;
+ backend_class->create_file_monitor = do_create_file_monitor;
+
+ /* fast sync versions that only succeed if info is in the cache */
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_query_fs_info = try_query_fs_info;
+}
diff --git a/trunk/daemon/gvfsbackendgphoto2.h b/trunk/daemon/gvfsbackendgphoto2.h
new file mode 100644
index 00000000..33ad88a5
--- /dev/null
+++ b/trunk/daemon/gvfsbackendgphoto2.h
@@ -0,0 +1,51 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_GPHOTO2_H__
+#define __G_VFS_BACKEND_GPHOTO2_H__
+
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_GPHOTO2 (g_vfs_backend_gphoto2_get_type ())
+#define G_VFS_BACKEND_GPHOTO2(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_GPHOTO2, GVfsBackendGphoto2))
+#define G_VFS_BACKEND_GPHOTO2_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_GPHOTO2, GVfsBackendGphoto2Class))
+#define G_VFS_IS_BACKEND_GPHOTO2(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_GPHOTO2))
+#define G_VFS_IS_BACKEND_GPHOTO2_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_GPHOTO2))
+#define G_VFS_BACKEND_GPHOTO2_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_GPHOTO2, GVfsBackendGphoto2Class))
+
+typedef struct _GVfsBackendGphoto2 GVfsBackendGphoto2;
+typedef struct _GVfsBackendGphoto2Class GVfsBackendGphoto2Class;
+
+struct _GVfsBackendGphoto2Class
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_gphoto2_get_type (void) G_GNUC_CONST;
+
+GVfsBackendGphoto2 *g_vfs_backend_gphoto2_new (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_GPHOTO2_H__ */
diff --git a/trunk/daemon/gvfsbackendhttp.c b/trunk/daemon/gvfsbackendhttp.c
new file mode 100644
index 00000000..45ea54da
--- /dev/null
+++ b/trunk/daemon/gvfsbackendhttp.c
@@ -0,0 +1,685 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <libsoup/soup-gnome.h>
+#include "gvfsbackendhttp.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+
+#include "soup-input-stream.h"
+
+
+G_DEFINE_TYPE (GVfsBackendHttp, g_vfs_backend_http, G_VFS_TYPE_BACKEND)
+
+static void
+g_vfs_backend_http_finalize (GObject *object)
+{
+ GVfsBackendHttp *backend;
+
+ backend = G_VFS_BACKEND_HTTP (object);
+
+ if (backend->mount_base)
+ soup_uri_free (backend->mount_base);
+
+ soup_session_abort (backend->session);
+ g_object_unref (backend->session);
+
+ soup_session_abort (backend->session_async);
+ g_object_unref (backend->session_async);
+
+
+ if (G_OBJECT_CLASS (g_vfs_backend_http_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_http_parent_class)->finalize) (object);
+}
+
+#define DEBUG_MAX_BODY_SIZE (100 * 1024 * 1024)
+
+static void
+g_vfs_backend_http_init (GVfsBackendHttp *backend)
+{
+ const char *debug;
+ SoupSessionFeature *proxy_resolver;
+
+ g_vfs_backend_set_user_visible (G_VFS_BACKEND (backend), FALSE);
+
+ backend->session = soup_session_sync_new_with_options ("user-agent",
+ "gvfs/" VERSION,
+ NULL);
+
+ backend->session_async = soup_session_async_new_with_options ("user-agent",
+ "gvfs/" VERSION,
+ NULL);
+
+ /* Proxy handling */
+ proxy_resolver = g_object_new (SOUP_TYPE_PROXY_RESOLVER_GNOME, NULL);
+ soup_session_add_feature (backend->session, proxy_resolver);
+ soup_session_add_feature (backend->session_async, proxy_resolver);
+ g_object_unref (proxy_resolver);
+
+ /* Logging */
+ debug = g_getenv ("GVFS_HTTP_DEBUG");
+ if (debug)
+ {
+ SoupLogger *logger;
+ SoupLoggerLogLevel level;
+
+ if (g_ascii_strcasecmp (debug, "all") ||
+ g_ascii_strcasecmp (debug, "body"))
+ level = SOUP_LOGGER_LOG_BODY;
+ else if (g_ascii_strcasecmp (debug, "header"))
+ level = SOUP_LOGGER_LOG_HEADERS;
+ else
+ level = SOUP_LOGGER_LOG_MINIMAL;
+
+ logger = soup_logger_new (level, DEBUG_MAX_BODY_SIZE);
+ soup_session_add_feature (backend->session, SOUP_SESSION_FEATURE (logger));
+ soup_session_add_feature (backend->session_async, SOUP_SESSION_FEATURE (logger));
+ g_object_unref (logger);
+ }
+
+}
+
+/* ************************************************************************* */
+/* public utility functions */
+
+SoupURI *
+http_backend_uri_for_filename (GVfsBackend *backend,
+ const char *filename,
+ gboolean is_dir)
+{
+ GVfsBackendHttp *op_backend;
+ SoupURI *uri;
+ char *path;
+
+ op_backend = G_VFS_BACKEND_HTTP (backend);
+ uri = soup_uri_copy (op_backend->mount_base);
+
+ /* "/" means "whatever mount_base is" */
+ if (!strcmp (filename, "/"))
+ return uri;
+
+ /* Otherwise, we append filename to mount_base (which is assumed to
+ * be a directory in this case).
+ *
+ * Add a "/" in cases where it is likely that the url is going
+ * to be a directory to avoid redirections
+ */
+ if (is_dir == FALSE || g_str_has_suffix (filename, "/"))
+ path = g_build_path ("/", uri->path, filename, NULL);
+ else
+ path = g_build_path ("/", uri->path, filename, "/", NULL);
+
+ g_free (uri->path);
+ uri->path = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,
+ FALSE);
+ g_free (path);
+
+ return uri;
+}
+
+char *
+http_uri_get_basename (const char *uri_str)
+{
+ const char *parent;
+ const char *path;
+ char *to_free;
+ char *basename;
+ size_t len;
+
+ if (uri_str == NULL || *uri_str == '\0')
+ return NULL;
+
+ path = uri_str;
+
+ /* remove any leading slashes */
+ while (*path == '/' || *path == ' ')
+ path++;
+
+ len = strlen (path);
+
+ if (len == 0)
+ return g_strdup ("/");
+
+ /* remove any trailing slashes */
+ while (path[len - 1] == '/' || path[len - 1] == ' ')
+ len--;
+
+ parent = g_strrstr_len (path, len, "/");
+
+ if (parent)
+ {
+ parent++; /* skip the found / char */
+ to_free = g_strndup (parent, (len - (parent - path)));
+ }
+ else
+ to_free = g_strndup (path, len);
+
+ basename = soup_uri_decode (to_free);
+ g_free (to_free);
+
+ return basename;
+}
+
+guint
+http_error_code_from_status (guint status)
+{
+ switch (status) {
+
+ case SOUP_STATUS_CANT_RESOLVE:
+ case SOUP_STATUS_CANT_RESOLVE_PROXY:
+ return G_IO_ERROR_HOST_NOT_FOUND;
+
+ case SOUP_STATUS_CANCELLED:
+ return G_IO_ERROR_CANCELLED;
+
+ case SOUP_STATUS_UNAUTHORIZED:
+ case SOUP_STATUS_PAYMENT_REQUIRED:
+ case SOUP_STATUS_FORBIDDEN:
+ return G_IO_ERROR_PERMISSION_DENIED;
+
+ case SOUP_STATUS_NOT_FOUND:
+ case SOUP_STATUS_GONE:
+ return G_IO_ERROR_NOT_FOUND;
+
+ case SOUP_STATUS_GATEWAY_TIMEOUT:
+ return G_IO_ERROR_TIMED_OUT;
+ }
+
+ return G_IO_ERROR_FAILED;
+}
+
+
+static void
+g_vfs_job_failed_from_http_status (GVfsJob *job, guint status_code, const char *message)
+{
+ switch (status_code) {
+
+ case SOUP_STATUS_NOT_FOUND:
+ g_vfs_job_failed_literal (job, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ message);
+ break;
+
+ case SOUP_STATUS_UNAUTHORIZED:
+ case SOUP_STATUS_PAYMENT_REQUIRED:
+ case SOUP_STATUS_FORBIDDEN:
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("HTTP Client Error: %s"), message);
+ break;
+ default:
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("HTTP Error: %s"), message);
+ }
+}
+
+guint
+http_backend_send_message (GVfsBackend *backend,
+ SoupMessage *msg)
+{
+ GVfsBackendHttp *op_backend = G_VFS_BACKEND_HTTP (backend);
+
+ return soup_session_send_message (op_backend->session, msg);
+}
+
+void
+http_backend_queue_message (GVfsBackend *backend,
+ SoupMessage *msg,
+ SoupSessionCallback callback,
+ gpointer user_data)
+{
+ GVfsBackendHttp *op_backend = G_VFS_BACKEND_HTTP (backend);
+
+ soup_session_queue_message (op_backend->session_async, msg,
+ callback, user_data);
+}
+/* ************************************************************************* */
+/* virtual functions overrides */
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendHttp *op_backend;
+ const char *uri_str;
+ char *path;
+ SoupURI *uri;
+ GMountSpec *real_mount_spec;
+
+ op_backend = G_VFS_BACKEND_HTTP (backend);
+
+ uri = NULL;
+ uri_str = g_mount_spec_get (mount_spec, "uri");
+
+ if (uri_str)
+ uri = soup_uri_new (uri_str);
+
+ g_debug ("+ try_mount: %s\n", uri_str ? uri_str : "(null)");
+
+ if (uri == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return TRUE;
+ }
+
+ real_mount_spec = g_mount_spec_new ("http");
+ g_mount_spec_set (real_mount_spec, "uri", uri_str);
+
+ if (uri->path != NULL)
+ {
+ path = g_uri_unescape_string (uri->path, "/");
+ g_free (real_mount_spec->mount_prefix);
+ real_mount_spec->mount_prefix = g_mount_spec_canonicalize_path (path);
+ g_free (path);
+ }
+
+ g_vfs_backend_set_mount_spec (backend, real_mount_spec);
+
+ op_backend->mount_base = uri;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+/* *** open_read () *** */
+static void
+open_for_read_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GInputStream *stream;
+ GVfsJob *job;
+ gboolean res;
+ gboolean can_seek;
+ GError *error;
+
+ stream = G_INPUT_STREAM (source_object);
+ error = NULL;
+ job = G_VFS_JOB (user_data);
+
+ res = soup_input_stream_send_finish (stream,
+ result,
+ &error);
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+
+ g_error_free (error);
+ g_object_unref (stream);
+ return;
+ }
+
+ can_seek = G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream));
+
+ g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), can_seek);
+ g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), stream);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendHttp *op_backend;
+ GInputStream *stream;
+ SoupMessage *msg;
+ SoupURI *uri;
+
+ op_backend = G_VFS_BACKEND_HTTP (backend);
+ uri = http_backend_uri_for_filename (backend, filename, FALSE);
+ msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
+ soup_uri_free (uri);
+
+ soup_message_body_set_accumulate (msg->response_body, FALSE);
+
+ stream = soup_input_stream_new (op_backend->session_async, msg);
+ g_object_unref (msg);
+
+ soup_input_stream_send_async (stream,
+ G_PRIORITY_DEFAULT,
+ G_VFS_JOB (job)->cancellable,
+ open_for_read_ready,
+ job);
+ return TRUE;
+}
+
+/* *** read () *** */
+static void
+read_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GInputStream *stream;
+ GVfsJob *job;
+ GError *error;
+ gssize nread;
+
+ stream = G_INPUT_STREAM (source_object);
+ error = NULL;
+ job = G_VFS_JOB (user_data);
+
+ nread = g_input_stream_read_finish (stream, result, &error);
+
+ if (nread < 0)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ g_vfs_job_read_set_size (G_VFS_JOB_READ (job), nread);
+ g_vfs_job_succeeded (job);
+
+}
+
+static gboolean
+try_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GInputStream *stream;
+
+ stream = G_INPUT_STREAM (handle);
+
+ g_input_stream_read_async (stream,
+ buffer,
+ bytes_requested,
+ G_PRIORITY_DEFAULT,
+ G_VFS_JOB (job)->cancellable,
+ read_ready,
+ job);
+ return TRUE;
+}
+
+static gboolean
+try_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GInputStream *stream;
+ GError *error = NULL;
+
+ stream = G_INPUT_STREAM (handle);
+
+ if (!g_seekable_seek (G_SEEKABLE (stream), offset, type,
+ G_VFS_JOB (job)->cancellable, &error))
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ else
+ {
+ g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (stream)));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+/* *** read_close () *** */
+static void
+close_read_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GInputStream *stream;
+ GVfsJob *job;
+ GError *error;
+ gboolean res;
+
+ job = G_VFS_JOB (user_data);
+ stream = G_INPUT_STREAM (source_object);
+ res = g_input_stream_close_finish (stream,
+ result,
+ &error);
+ if (res == FALSE)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ error->domain,
+ error->code,
+ error->message);
+
+ g_error_free (error);
+ }
+ else
+ g_vfs_job_succeeded (job);
+
+ g_object_unref (stream);
+}
+
+static gboolean
+try_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GInputStream *stream;
+
+ stream = G_INPUT_STREAM (handle);
+
+ g_input_stream_close_async (stream,
+ G_PRIORITY_DEFAULT,
+ G_VFS_JOB (job)->cancellable,
+ close_read_ready,
+ job);
+ return TRUE;
+}
+
+
+/* *** query_info () *** */
+
+static void
+query_info_ready (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ GFileAttributeMatcher *matcher;
+ GVfsJobQueryInfo *job;
+ const SoupURI *uri;
+ const char *text;
+ GFileInfo *info;
+ char *basename;
+
+ job = G_VFS_JOB_QUERY_INFO (user_data);
+ info = job->file_info;
+ matcher = job->attribute_matcher;
+
+ if (! SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ g_vfs_job_failed_from_http_status (G_VFS_JOB (job), msg->status_code,
+ msg->reason_phrase);
+ return;
+ }
+
+ uri = soup_message_get_uri (msg);
+ basename = http_uri_get_basename (uri->path);
+
+ g_debug ("basename:%s\n", basename);
+
+ /* read http/1.1 rfc, until then we copy the local files
+ * behaviour */
+ if (basename != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
+ {
+ char *display_name = g_filename_display_name (basename);
+
+ if (strstr (display_name, "\357\277\275") != NULL)
+ {
+ char *p = display_name;
+ display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL);
+ g_free (p);
+ }
+
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+
+ if (basename != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME))
+ {
+ char *edit_name = g_filename_display_name (basename);
+ g_file_info_set_edit_name (info, edit_name);
+ g_free (edit_name);
+ }
+
+ g_free (basename);
+
+
+ text = soup_message_headers_get (msg->response_headers,
+ "Content-Length");
+ if (text)
+ {
+ guint64 size = g_ascii_strtoull (text, NULL, 10);
+ g_file_info_set_size (info, size);
+ }
+
+
+ text = soup_message_headers_get (msg->response_headers,
+ "Content-Type");
+ if (text)
+ {
+ char *p = strchr (text, ';');
+
+ if (p != NULL)
+ {
+ char *tmp = g_strndup (text, p - text);
+ g_file_info_set_content_type (info, tmp);
+ g_free (tmp);
+ }
+ else
+ g_file_info_set_content_type (info, text);
+ }
+
+
+ text = soup_message_headers_get (msg->response_headers,
+ "Last-Modified");
+ if (text)
+ {
+ SoupDate *sd;
+ GTimeVal tv;
+
+ sd = soup_date_new_from_string(text);
+ if (sd)
+ {
+ soup_date_to_timeval (sd, &tv);
+ g_file_info_set_modification_time (info, &tv);
+ soup_date_free (sd);
+ }
+ }
+
+
+ text = soup_message_headers_get (msg->response_headers,
+ "ETag");
+ if (text)
+ {
+ g_file_info_set_attribute_string (info,
+ G_FILE_ATTRIBUTE_ETAG_VALUE,
+ text);
+ }
+
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ SoupMessage *msg;
+ SoupURI *uri;
+
+ uri = http_backend_uri_for_filename (backend, filename, FALSE);
+ msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri);
+ soup_uri_free (uri);
+
+ http_backend_queue_message (backend, msg, query_info_ready, job);
+
+ return TRUE;
+}
+
+
+static void
+g_vfs_backend_http_class_init (GVfsBackendHttpClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class;
+
+ gobject_class->finalize = g_vfs_backend_http_finalize;
+
+ backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_read = try_read;
+ backend_class->try_seek_on_read = try_seek_on_read;
+ backend_class->try_close_read = try_close_read;
+ backend_class->try_query_info = try_query_info;
+
+}
diff --git a/trunk/daemon/gvfsbackendhttp.h b/trunk/daemon/gvfsbackendhttp.h
new file mode 100644
index 00000000..c3233246
--- /dev/null
+++ b/trunk/daemon/gvfsbackendhttp.h
@@ -0,0 +1,79 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_HTTP_H__
+#define __G_VFS_BACKEND_HTTP_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+#include <libsoup/soup.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_HTTP (g_vfs_backend_http_get_type ())
+#define G_VFS_BACKEND_HTTP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_HTTP, GVfsBackendHttp))
+#define G_VFS_BACKEND_HTTP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_HTTP, GVfsBackendHttpClass))
+#define G_VFS_IS_BACKEND_HTTP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_HTTP))
+#define G_VFS_IS_BACKEND_HTTP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_HTTP))
+#define G_VFS_BACKEND_HTTP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_HTTP, GVfsBackendHttpClass))
+
+typedef struct _GVfsBackendHttp GVfsBackendHttp;
+typedef struct _GVfsBackendHttpClass GVfsBackendHttpClass;
+
+struct _GVfsBackendHttpClass
+{
+ GVfsBackendClass parent_class;
+
+};
+
+struct _GVfsBackendHttp
+{
+ GVfsBackend parent_instance;
+
+ SoupURI *mount_base;
+ SoupSession *session;
+
+ SoupSession *session_async;
+};
+
+GType g_vfs_backend_http_get_type (void) G_GNUC_CONST;
+
+SoupURI * http_backend_uri_for_filename (GVfsBackend *backend,
+ const char *filename,
+ gboolean is_dir);
+
+
+char * http_uri_get_basename (const char *uri_str);
+
+guint http_error_code_from_status (guint status);
+
+guint http_backend_send_message (GVfsBackend *backend,
+ SoupMessage *msg);
+
+void http_backend_queue_message (GVfsBackend *backend,
+ SoupMessage *msg,
+ SoupSessionCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_HTTP_H__ */
diff --git a/trunk/daemon/gvfsbackendlocaltest.c b/trunk/daemon/gvfsbackendlocaltest.c
new file mode 100644
index 00000000..ac30adcd
--- /dev/null
+++ b/trunk/daemon/gvfsbackendlocaltest.c
@@ -0,0 +1,1252 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * Local testing backend wrapping error injection
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Tomas Bzatek <tbzatek@redhat.com>
+ */
+
+
+/*** USAGE:
+ *
+ * - behaviour is controlled via environment variable (i.e. set from the shell, before launching /usr/libexec/gvfsd)
+ * GVFS_ERRORNEOUS: number, how often operation should fail (a random() is used, this number is not a sequence)
+ * GVFS_ERRORNEOUS_OPS: bitmask of operations to fail - see GVfsJobType enum
+ *
+ ***/
+
+
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gvfsbackendlocaltest.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobdelete.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsmonitor.h"
+
+
+/* TODO:
+ * Bugs:
+ * - unmounting ?
+ * - copy dialog still visible after try_copy() finished successfully --> temporarily disabled do_copy ()
+ *
+ *
+ * Conceptual:
+ * - closing directory/file monitor - after a Nautilus window is closed, no method is called to destroy the monitor object
+ * - find a better way how to pass parameters to a running instance of gvfsd-localtest
+ *
+ */
+
+
+
+
+
+/************************************************
+ * Error injection
+ *
+ */
+
+
+static gboolean
+inject_error (GVfsBackend *backend,
+ GVfsJob *job,
+ GVfsJobType job_type)
+{
+ GVfsBackendLocalTest *op_backend = G_VFS_BACKEND_LOCALTEST (backend);
+
+ if ((op_backend->errorneous > 0) && ((random() % op_backend->errorneous) == 0) &&
+ ((op_backend->inject_op_types < 1) || ((op_backend->inject_op_types & job_type) == job_type)))
+ {
+ g_print ("(II) inject_error: BANG! injecting error... \n");
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Injected error");
+ return FALSE;
+ } else g_vfs_job_succeeded (job);
+ return TRUE;
+}
+
+
+
+
+
+/************************************************
+ * Utility functions
+ *
+ */
+
+/* returned object should be freed in user's function */
+static GFile*
+get_g_file_from_local (const char *filename, GVfsJob *job)
+{
+ GVfs *local_vfs;
+ GFile *file = NULL;
+
+ local_vfs = g_vfs_get_local ();
+ if (! local_vfs) {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Cannot get local vfs");
+ g_print (" (EE) get_g_file_from_local (filename = '%s'): local_vfs == NULL \n", filename);
+ return NULL;
+ }
+
+ file = g_vfs_get_file_for_path (local_vfs, filename);
+ if (! file) {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Cannot get file from local vfs");
+ g_print (" (EE) get_g_file_from_local (filename = '%s'): file == NULL \n", filename);
+ return NULL;
+ }
+ return file;
+}
+
+/* returned object should be freed in user's function */
+static GFileInfo*
+get_g_file_info_from_local (const char *filename, GFile *file,
+ const char *attributes, GFileQueryInfoFlags flags,
+ GVfsJob *job)
+{
+ GError *error;
+ GFileInfo *info = NULL;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ if (file) {
+ error = NULL;
+ info = g_file_query_info (file, attributes, flags, G_VFS_JOB (job)->cancellable, &error);
+
+ if ((error) || (! info) ) {
+ g_print (" (EE) get_g_file_info_from_local (filename = '%s'): g_file_query_info failed: %s \n", filename, error->message);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return NULL;
+ }
+ }
+ return info;
+}
+
+
+
+
+
+
+
+/************************************************
+ * Initialization
+ *
+ */
+
+G_DEFINE_TYPE (GVfsBackendLocalTest, g_vfs_backend_localtest, G_VFS_TYPE_BACKEND)
+
+static void
+g_vfs_backend_localtest_init (GVfsBackendLocalTest *backend)
+{
+ const char *c;
+
+ /* Nothing in there */
+ g_print ("(II) g_vfs_backend_localtest_init \n");
+
+ /* env var conversion */
+ backend->errorneous = -1;
+ backend->inject_op_types = -1;
+
+ c = g_getenv("GVFS_ERRORNEOUS");
+ if (c) {
+ backend->errorneous = g_ascii_strtoll(c, NULL, 0);
+ g_print ("(II) g_vfs_backend_localtest_init: setting 'errorneous' to '%d' \n", backend->errorneous);
+ }
+
+ c = g_getenv("GVFS_ERRORNEOUS_OPS");
+ if (c) {
+ backend->inject_op_types = g_ascii_strtoll(c, NULL, 0);
+ g_print ("(II) g_vfs_backend_localtest_init: setting 'inject_op_types' to '%lu' \n", (unsigned long)backend->inject_op_types);
+ }
+
+ g_print ("(II) g_vfs_backend_localtest_init done.\n");
+}
+
+static void
+g_vfs_backend_localtest_finalize (GObject *object)
+{
+ GVfsBackendLocalTest *backend;
+
+ g_print ("(II) g_vfs_backend_localtest_finalize \n");
+
+ backend = G_VFS_BACKEND_LOCALTEST (object);
+
+ if (backend->test)
+ g_free ((gpointer)backend->test);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_localtest_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_localtest_parent_class)->finalize) (object);
+}
+
+
+
+
+
+
+
+/************************************************
+ * Mount
+ *
+ */
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendLocalTest *op_backend = G_VFS_BACKEND_LOCALTEST (backend);
+
+ g_print ("(II) try_mount \n");
+
+ g_vfs_backend_set_display_name (backend, "localtest");
+
+ op_backend->mount_spec = g_mount_spec_new ("localtest");
+ g_vfs_backend_set_mount_spec (backend, op_backend->mount_spec);
+
+ g_vfs_backend_set_icon_name (backend, "folder-remote");
+
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_MOUNT);
+}
+
+
+static void
+do_unmount (GVfsBackend *backend, GVfsJobUnmount *job)
+{
+ GVfsBackendLocalTest *op_backend;
+
+ g_print ("(II) try_umount \n");
+
+ op_backend = G_VFS_BACKEND_LOCALTEST (backend);
+ g_mount_spec_unref (op_backend->mount_spec);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_UNMOUNT);
+}
+
+
+
+
+
+
+
+/************************************************
+ * Queries
+ *
+ */
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GFile *file;
+ GFileInfo *info;
+ GError *error;
+ GFileEnumerator *enumerator;
+ gboolean res;
+
+ g_print ("(II) try_enumerate (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+ res = TRUE;
+
+ error = NULL;
+ enumerator = g_file_enumerate_children (file, "*", flags, G_VFS_JOB (job)->cancellable, &error);
+ if (enumerator) {
+ error = NULL;
+ while ((info = g_file_enumerator_next_file (enumerator, G_VFS_JOB (job)->cancellable, &error)) != NULL) {
+ g_print (" (II) try_enumerate (filename = %s): file '%s' \n", filename, g_file_info_get_attribute_string(info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME));
+ g_vfs_job_enumerate_add_info (job, info);
+ }
+ if (error) {
+ g_print (" (EE) try_enumerate: error: %s \n", error->message);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ res = FALSE;
+ } else
+ res = inject_error (backend, G_VFS_JOB (job), GVFS_JOB_ENUMERATE);
+
+ error = NULL;
+ g_file_enumerator_close (enumerator, G_VFS_JOB (job)->cancellable, &error);
+ if (error) {
+ g_print (" (EE) try_enumerate: g_file_enumerator_close() error: %s \n", error->message);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ res = FALSE;
+ }
+ g_object_unref (enumerator);
+ g_print (" (II) try_enumerate: success. \n");
+ } else {
+ if (error) {
+ g_print (" (EE) try_enumerate: error: %s \n", error->message);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ res = FALSE;
+ } else {
+ g_print (" (EE) try_enumerate: error == NULL \n");
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Error try_enumerate");
+ res = FALSE;
+ }
+ }
+
+ g_object_unref (file);
+ if (res) {
+ g_vfs_job_enumerate_done (job);
+ }
+
+ g_print ("(II) try_enumerate done. \n");
+}
+
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GFile *file;
+ GFileInfo *info2;
+
+ g_print ("(II) try_query_info (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ info2 = get_g_file_info_from_local (filename, file, "*", flags, G_VFS_JOB (job));
+
+ if (info2) {
+ g_file_info_copy_into (info2, info);
+ g_object_unref (info2);
+ g_object_unref (file);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_QUERY_INFO);
+ g_print ("(II) try_query_info success. \n");
+ } else
+ g_print ("(EE) try_query_info failed. \n");
+}
+
+
+static void
+do_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GFile *file;
+ GFileInfo *info2;
+ GError *error;
+
+ g_print ("(II) try_query_fs_info (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+
+ if (file) {
+ error = NULL;
+ info2 = g_file_query_filesystem_info (file, "fs:*", G_VFS_JOB (job)->cancellable, &error);
+ if ((error) || (! info2) ) {
+ g_print (" (EE) try_query_fs_info (filename = '%s'): g_file_query_filesystem_info failed: %s \n", filename, error->message);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ } else {
+ g_file_info_copy_into (info2, info);
+ g_object_unref (info2);
+ g_object_unref (file);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_QUERY_FS_INFO);
+ g_print ("(II) try_query_fs_info success. \n");
+ }
+ } else {
+ g_print ("(EE) try_query_fs_info failed. \n");
+ }
+}
+
+
+static void
+do_query_settable_attributes (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename)
+{
+ GFileAttributeInfoList *attr_list;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_query_settable_attributes (filename = '%s') \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ attr_list = g_file_query_settable_attributes (file, G_VFS_JOB (job)->cancellable, &error);
+ if ((attr_list) && (! error)) {
+ g_vfs_job_query_attributes_set_list (job, attr_list);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_QUERY_SETTABLE_ATTRIBUTES);
+ g_print ("(II) try_query_settable_attributes success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_query_settable_attributes: g_file_query_settable_attributes == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_query_settable_attributes: file == NULL \n");
+ }
+}
+
+static void
+do_query_writable_namespaces (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename)
+{
+ GFileAttributeInfoList *attr_list;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_query_writable_namespaces (filename = '%s') \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ attr_list = g_file_query_writable_namespaces (file, G_VFS_JOB (job)->cancellable, &error);
+ if ((attr_list) && (! error)) {
+ g_vfs_job_query_attributes_set_list (job, attr_list);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_QUERY_WRITABLE_NAMESPACES);
+ g_print ("(II) try_query_writable_namespaces success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_query_writable_namespaces: g_file_query_writable_namespaces == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_query_writable_namespaces: file == NULL \n");
+ }
+}
+
+
+
+
+
+/************************************************
+ * Operations
+ *
+ */
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_make_directory (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_make_directory (file, G_VFS_JOB (job)->cancellable, &error)) {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_MAKE_DIRECTORY);
+ g_print ("(II) try_make_directory success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_make_directory: g_file_make_directory == FALSE \n");
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_make_directory: file == NULL \n");
+ }
+}
+
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_delete (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_delete (file, G_VFS_JOB (job)->cancellable, &error)) {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_DELETE);
+ g_print ("(II) try_delete success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_delete: g_file_delete == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_delete: file == NULL \n");
+ }
+}
+
+
+static void
+do_trash (GVfsBackend *backend,
+ GVfsJobTrash *job,
+ const char *filename)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_trash (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_trash (file, G_VFS_JOB (job)->cancellable, &error)) {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_TRASH);
+ g_print ("(II) try_trash success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_trash: g_file_trash == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_trash: file == NULL \n");
+ }
+}
+
+
+static void
+do_make_symlink (GVfsBackend *backend,
+ GVfsJobMakeSymlink *job,
+ const char *filename,
+ const char *symlink_value)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_make_symlink ('%s' --> '%s') \n", filename, symlink_value);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_make_symbolic_link (file, symlink_value, G_VFS_JOB (job)->cancellable, &error)) {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_MAKE_SYMLINK);
+ g_print ("(II) try_make_symlink success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_make_symlink: g_file_make_symbolic_link == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_make_symlink: file == NULL \n");
+ }
+}
+
+#if 0
+static void
+do_copy (GVfsBackend *backend,
+ GVfsJobCopy *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GFile *src_file, *dst_file;
+ GError *error;
+
+ g_print ("(II) try_copy '%s' --> '%s' \n", source, destination);
+
+ src_file = get_g_file_from_local (source, G_VFS_JOB (job));
+ dst_file = get_g_file_from_local (destination, G_VFS_JOB (job));
+ g_assert (src_file != NULL);
+
+ if (src_file) {
+ error = NULL;
+ if (g_file_copy (src_file, dst_file, flags, G_VFS_JOB (job)->cancellable,
+ progress_callback, progress_callback_data, &error))
+ {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_COPY);
+ g_print (" (II) try_copy: success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_copy: g_file_copy == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (src_file);
+ g_object_unref (dst_file);
+ } else {
+ g_print (" (EE) try_copy: file == NULL \n");
+ }
+}
+#endif
+
+static void
+do_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GFile *src_file, *dst_file;
+ GError *error;
+
+ g_print ("(II) try_move '%s' --> '%s' \n", source, destination);
+
+ src_file = get_g_file_from_local (source, G_VFS_JOB (job));
+ dst_file = get_g_file_from_local (destination, G_VFS_JOB (job));
+ g_assert (src_file != NULL);
+
+ if (src_file) {
+ error = NULL;
+ if (g_file_move (src_file, dst_file, flags, G_VFS_JOB (job)->cancellable,
+ progress_callback, progress_callback_data, &error))
+ {
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_MOVE);
+ g_print (" (II) try_move: success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_move: g_file_move == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (src_file);
+ g_object_unref (dst_file);
+ } else {
+ g_print (" (EE) try_move: file == NULL \n");
+ }
+}
+
+
+// aka 'rename'
+static void
+do_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_set_display_name '%s' --> '%s' \n", filename, display_name);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_set_display_name (file, display_name, G_VFS_JOB (job)->cancellable, &error)) {
+ char *dirname, *new_path;
+ dirname = g_path_get_dirname (filename);
+ new_path = g_build_filename (dirname, display_name, NULL);
+ g_print ("(II) try_set_display_name: filename = '%s'... \n", filename);
+ g_print ("(II) try_set_display_name: display_name = '%s'... \n", display_name);
+ g_print ("(II) try_set_display_name: dirname = '%s'... \n", dirname);
+ g_print ("(II) try_set_display_name: new_path = '%s'... \n", new_path);
+ g_vfs_job_set_display_name_set_new_path (job, new_path);
+ g_free (dirname);
+ g_free (new_path);
+
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_SET_DISPLAY_NAME);
+ g_print ("(II) try_set_display_name success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_set_display_name: g_file_set_display_name == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_set_display_name: file == NULL \n");
+ }
+}
+
+
+static void
+do_set_attribute (GVfsBackend *backend,
+ GVfsJobSetAttribute *set_attribute,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags)
+{
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_set_attribute (filename = '%s', attribute = '%s') \n", filename, attribute);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (set_attribute));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ if (g_file_set_attribute (file, attribute, type, value_p, flags, G_VFS_JOB (set_attribute)->cancellable, &error)) {
+ inject_error (backend, G_VFS_JOB (set_attribute), GVFS_JOB_SET_ATTRIBUTE);
+ g_print ("(II) try_set_attribute success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (set_attribute), error);
+ g_print (" (EE) try_set_attribute: g_file_set_attribute == FALSE, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_set_attribute: file == NULL \n");
+ }
+}
+
+
+
+
+
+
+
+/************************************************
+ * Monitors
+ *
+ */
+
+/* MonitorProxy has been stolen from gvfsbackendtrash */
+typedef struct {
+ GVfsMonitor *vfs_monitor;
+ GObject *monitor;
+} MonitorProxy;
+
+static void
+monitor_proxy_free (MonitorProxy *proxy)
+{
+ g_print ("(II) monitor_proxy_free \n");
+ g_object_unref (proxy->monitor);
+ g_free (proxy);
+}
+
+static void
+proxy_changed (GFileMonitor* monitor,
+ GFile* file,
+ GFile* other_file,
+ GFileMonitorEvent event_type,
+ MonitorProxy *proxy)
+{
+ char *file_path;
+ char *other_file_path;
+
+ file_path = g_file_get_path (file);
+ g_print ("(II) monitor_proxy_changed: file_path = '%s' \n", file_path);
+
+ if (other_file)
+ {
+ other_file_path = g_file_get_path (other_file);
+ g_print ("(II) monitor_proxy_changed: other_file_path == '%s' \n", other_file_path);
+ }
+ else
+ {
+ other_file_path = NULL;
+ }
+
+ g_vfs_monitor_emit_event (proxy->vfs_monitor,
+ event_type,
+ file_path,
+ other_file_path);
+
+ g_free (file_path);
+ g_free (other_file_path);
+}
+
+
+static void
+create_dir_file_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags,
+ const gboolean is_dir_monitor)
+{
+ GObject *monitor;
+ MonitorProxy *proxy;
+ GFile *file;
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (is_dir_monitor) {
+ monitor = G_OBJECT (g_file_monitor_directory (file, flags, G_VFS_JOB (job)->cancellable, NULL));
+ } else {
+ monitor = G_OBJECT (g_file_monitor_file (file, flags, G_VFS_JOB (job)->cancellable, NULL));
+ }
+
+ if (monitor) {
+ proxy = g_new0 (MonitorProxy, 1);
+ proxy->vfs_monitor = g_vfs_monitor_new (backend);
+ proxy->monitor = monitor;
+
+ g_object_set_data_full (G_OBJECT (proxy->vfs_monitor), "monitor-proxy",
+ proxy, (GDestroyNotify) monitor_proxy_free); //* hmm?
+ g_signal_connect (monitor, "changed", G_CALLBACK (proxy_changed), proxy);
+
+ g_vfs_job_create_monitor_set_monitor (job, proxy->vfs_monitor);
+
+ g_object_unref (proxy->vfs_monitor);
+
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_CREATE_DIR_MONITOR);
+ g_print ("(II) create_dir_file_monitor success. \n");
+ }
+ else {
+ g_print (" (EE) create_dir_file_monitor: monitor == NULL \n");
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Directory notification not supported"));
+ }
+ g_object_unref (file);
+}
+
+
+static void
+do_create_dir_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ g_print ("(II) try_create_dir_monitor (filename = '%s') \n", filename);
+ create_dir_file_monitor (backend, job, filename, flags, TRUE);
+}
+
+
+static void
+do_create_file_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ g_print ("(II) try_create_file_monitor (filename = '%s') \n", filename);
+ create_dir_file_monitor (backend, job, filename, flags, FALSE);
+}
+
+
+
+
+
+
+/************************************************
+ * Read/write/create/close data operations
+ *
+ */
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GFileInputStream *stream;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_open_for_read (filename = '%s') \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ stream = g_file_read (file, G_VFS_JOB (job)->cancellable, &error);
+ if (stream) {
+ g_vfs_job_open_for_read_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
+ g_vfs_job_open_for_read_set_handle (job, stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_OPEN_FOR_READ);
+ g_print ("(II) try_open_for_read success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_open_for_read: stream == NULL, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_open_for_read: file == NULL \n");
+ }
+}
+
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+ gssize s;
+
+ g_print ("(II) try_read (handle = '%lx', buffer = '%lx', bytes_requested = %ld) \n",
+ (long int)_handle, (long int)buffer, (long int)bytes_requested);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ s = g_input_stream_read (G_INPUT_STREAM (stream), buffer, bytes_requested,
+ G_VFS_JOB (job)->cancellable, &error);
+ if (s >= 0) {
+ g_vfs_job_read_set_size (job, s);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_READ);
+ g_print ("(II) try_read success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_read: g_input_stream_read() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+
+ g_print ("(II) try_seek_on_read (handle = '%lx', offset = %ld) \n", (long int)_handle, (long int)offset);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ if (g_seekable_seek (G_SEEKABLE (stream), offset, type, G_VFS_JOB (job)->cancellable, &error)) {
+ g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (stream)));
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_SEEK_ON_READ);
+ g_print ("(II) try_seek_on_read success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_seek_on_read: g_file_input_stream_seek() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle _handle)
+{
+ GError *error;
+ GFileInputStream *stream = _handle;
+
+ g_print ("(II) try_close_read (handle = '%lx') \n", (long int)_handle);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ if (g_input_stream_close (G_INPUT_STREAM (stream), G_VFS_JOB (job)->cancellable, &error)) {
+ g_object_unref (stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_CLOSE_READ);
+ g_print ("(II) try_close_read success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_close_read: g_input_stream_close() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GFileOutputStream *stream;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_append_to (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ stream = g_file_append_to (file, flags, G_VFS_JOB (job)->cancellable, &error);
+ if (stream) {
+ /* Should seek at the end of the file here */
+ if ((g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_END, G_VFS_JOB (job)->cancellable, &error)) && (! error)) {
+ g_vfs_job_open_for_write_set_initial_offset (job, g_seekable_tell (G_SEEKABLE (stream)));
+ } else {
+ g_print (" (EE) try_append_to: error during g_file_output_stream_seek(), error: %s \n", error->message);
+ }
+
+ g_vfs_job_open_for_write_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
+ g_vfs_job_open_for_write_set_handle (job, stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_APPEND_TO);
+
+ g_print ("(II) try_append_to success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_append_to: stream == NULL, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_append_to: file == NULL \n");
+ }
+}
+
+
+static void
+do_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GFileOutputStream *stream;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_create (filename = %s) \n", filename);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ stream = g_file_create (file, flags, G_VFS_JOB (job)->cancellable, &error);
+ if (stream) {
+ g_vfs_job_open_for_write_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
+ g_vfs_job_open_for_write_set_handle (job, stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_CREATE);
+ g_print ("(II) try_create success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_create: stream == NULL, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_create: file == NULL \n");
+ }
+}
+
+
+static void
+do_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GFileOutputStream *stream;
+ GError *error;
+ GFile *file;
+
+ g_print ("(II) try_replace (filename = '%s', etag = '%s') \n", filename, etag);
+
+ file = get_g_file_from_local (filename, G_VFS_JOB (job));
+ g_assert (file != NULL);
+
+ if (file) {
+ error = NULL;
+ stream = g_file_replace (file, etag, make_backup, flags, G_VFS_JOB (job)->cancellable, &error);
+ if (stream) {
+ g_vfs_job_open_for_write_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
+ g_vfs_job_open_for_write_set_handle (job, stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_REPLACE);
+ g_print ("(II) try_replace success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_replace: stream == NULL, error: %s \n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ } else {
+ g_print (" (EE) try_replace: file == NULL \n");
+ }
+}
+
+
+static void
+do_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ GError *error;
+ GFileOutputStream *stream = _handle;
+ gssize s;
+
+ g_print ("(II) try_write (handle = '%lx', buffer = '%lx', buffer_size = %ld) \n",
+ (long int)_handle, (long int)buffer, (long int)buffer_size);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ s = g_output_stream_write (G_OUTPUT_STREAM (stream), buffer, buffer_size, G_VFS_JOB (job)->cancellable, &error);
+ if (s >= 0) {
+ g_vfs_job_write_set_written_size (job, s);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_WRITE);
+ g_print ("(II) try_write success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_write: g_output_stream_write() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_seek_on_write (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ GError *error;
+ GFileOutputStream *stream = _handle;
+
+ g_print ("(II) try_seek_on_write (handle = '%lx', offset = %ld) \n", (long int)_handle, (long int)offset);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ if (g_seekable_seek (G_SEEKABLE (stream), offset, type, G_VFS_JOB (job)->cancellable, &error)) {
+ g_vfs_job_seek_write_set_offset (job, g_seekable_tell (G_SEEKABLE (stream)));
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_SEEK_ON_WRITE);
+ g_print ("(II) try_seek_on_write success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_seek_on_write: g_file_output_stream_seek() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+static void
+do_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle _handle)
+{
+ GError *error;
+ GFileOutputStream *stream = _handle;
+
+ g_print ("(II) try_close_write (handle = '%lx') \n", (long int)_handle);
+
+ g_assert (stream != NULL);
+
+ error = NULL;
+ if (g_output_stream_close (G_OUTPUT_STREAM(stream), G_VFS_JOB (job)->cancellable, &error)) {
+ g_object_unref (stream);
+ inject_error (backend, G_VFS_JOB (job), GVFS_JOB_CLOSE_WRITE);
+ g_print ("(II) try_close_write success. \n");
+ } else {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_print (" (EE) try_close_write: g_input_stream_close() failed, error: %s \n", error->message);
+ g_error_free (error);
+ }
+}
+
+
+
+
+
+
+
+
+/************************************************
+ * Class init
+ *
+ */
+
+
+static void
+g_vfs_backend_localtest_class_init (GVfsBackendLocalTestClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_localtest_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->unmount = do_unmount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->read = do_read;
+ backend_class->seek_on_read = do_seek_on_read;
+ backend_class->close_read = do_close_read;
+ backend_class->close_write = do_close_write;
+ backend_class->query_info = do_query_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->query_fs_info = do_query_fs_info;
+ backend_class->create = do_create;
+ backend_class->append_to = do_append_to;
+ backend_class->replace = do_replace;
+ backend_class->write = do_write;
+ backend_class->seek_on_write = do_seek_on_write;
+/* -- disabled, read/write operations can handle copy correctly */
+/* backend_class->copy = do_copy; */
+ backend_class->move = do_move;
+ backend_class->make_symlink = do_make_symlink;
+ backend_class->make_directory = do_make_directory;
+ backend_class->delete = do_delete;
+ backend_class->trash = do_trash;
+ backend_class->set_display_name = do_set_display_name;
+ backend_class->set_attribute = do_set_attribute;
+ backend_class->create_dir_monitor = do_create_dir_monitor;
+ backend_class->create_file_monitor = do_create_file_monitor;
+ backend_class->query_settable_attributes = do_query_settable_attributes;
+ backend_class->query_writable_namespaces = do_query_writable_namespaces;
+}
diff --git a/trunk/daemon/gvfsbackendlocaltest.h b/trunk/daemon/gvfsbackendlocaltest.h
new file mode 100644
index 00000000..71db179e
--- /dev/null
+++ b/trunk/daemon/gvfsbackendlocaltest.h
@@ -0,0 +1,94 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * Local testing backend wrapping error injection
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Tomas Bzatek <tbzatek@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_LOCALTEST_H__
+#define __G_VFS_BACKEND_LOCALTEST_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_LOCALTEST (g_vfs_backend_localtest_get_type ())
+#define G_VFS_BACKEND_LOCALTEST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_LOCALTEST, GVfsBackendLocalTest))
+#define G_VFS_BACKEND_LOCALTEST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_LOCALTEST, GVfsBackendLocalTestClass))
+#define G_VFS_IS_BACKEND_LOCALTEST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_LOCALTEST))
+#define G_VFS_IS_BACKEND_LOCALTEST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_LOCALTEST))
+#define G_VFS_BACKEND_LOCALTEST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_LOCALTEST, GVfsBackendLocalTestClass))
+
+typedef struct _GVfsBackendLocalTest GVfsBackendLocalTest;
+typedef struct _GVfsBackendLocalTestClass GVfsBackendLocalTestClass;
+
+
+
+typedef enum {
+ GVFS_JOB_UNMOUNT = 1<<0,
+ GVFS_JOB_MOUNT = 1<<1,
+ GVFS_JOB_OPEN_FOR_READ = 1<<2,
+ GVFS_JOB_CLOSE_READ = 1<<3,
+ GVFS_JOB_READ = 1<<4,
+ GVFS_JOB_SEEK_ON_READ = 1<<5,
+ GVFS_JOB_CREATE = 1<<6,
+ GVFS_JOB_APPEND_TO = 1<<7,
+ GVFS_JOB_REPLACE = 1<<8,
+ GVFS_JOB_CLOSE_WRITE = 1<<9,
+ GVFS_JOB_WRITE = 1<<10,
+ GVFS_JOB_SEEK_ON_WRITE = 1<<11,
+ GVFS_JOB_QUERY_INFO = 1<<12,
+ GVFS_JOB_QUERY_FS_INFO = 1<<13,
+ GVFS_JOB_ENUMERATE = 1<<14,
+ GVFS_JOB_SET_DISPLAY_NAME = 1<<15,
+ GVFS_JOB_DELETE = 1<<16,
+ GVFS_JOB_TRASH = 1<<17,
+ GVFS_JOB_MAKE_DIRECTORY = 1<<18,
+ GVFS_JOB_MAKE_SYMLINK = 1<<19,
+ GVFS_JOB_COPY = 1<<20,
+ GVFS_JOB_MOVE = 1<<21,
+ GVFS_JOB_SET_ATTRIBUTE = 1<<22,
+ GVFS_JOB_CREATE_DIR_MONITOR = 1<<23,
+ GVFS_JOB_CREATE_FILE_MONITOR = 1<<24,
+ GVFS_JOB_QUERY_SETTABLE_ATTRIBUTES = 1<<25,
+ GVFS_JOB_QUERY_WRITABLE_NAMESPACES = 1<<26
+} GVfsJobType;
+
+
+
+struct _GVfsBackendLocalTest
+{
+ GVfsBackend parent_instance;
+ const gchar *test;
+ GMountSpec *mount_spec;
+ int errorneous;
+ GVfsJobType inject_op_types;
+};
+
+struct _GVfsBackendLocalTestClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_localtest_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_LOCALTEST_H__ */
diff --git a/trunk/daemon/gvfsbackendnetwork.c b/trunk/daemon/gvfsbackendnetwork.c
new file mode 100644
index 00000000..5fe0e4a8
--- /dev/null
+++ b/trunk/daemon/gvfsbackendnetwork.c
@@ -0,0 +1,933 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Alexander Larsson <alexl@redhat.com>
+ * Andrew Walton <awalton@svn.gnome.org> (port only)
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gconf/gconf-client.h>
+
+#include "gvfsbackendnetwork.h"
+
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsmonitor.h"
+
+#define PATH_GCONF_GVFS_SMB "/system/smb"
+#define PATH_GCONF_GVFS_SMB_WORKGROUP "/system/smb/workgroup"
+#define DEFAULT_WORKGROUP_NAME "X-GNOME-DEFAULT-WORKGROUP"
+
+#define PATH_GCONF_GVFS_DNS_SD "/system/dns_sd"
+#define PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL "/system/dns_sd/display_local"
+#define PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS "/system/dns_sd/extra_domains"
+
+#define NETWORK_FILE_ATTRIBUTES "standard::name,standard::display-name,standard::target-uri"
+
+typedef struct {
+ char *file_name;
+ char *display_name;
+ char *target_uri;
+ GIcon *icon;
+} NetworkFile;
+
+static NetworkFile root = { "/" };
+
+typedef enum {
+ NETWORK_LOCAL_DISABLED,
+ NETWORK_LOCAL_MERGED,
+ NETWORK_LOCAL_SEPARATE
+} NetworkLocalSetting;
+
+struct _GVfsBackendNetwork
+{
+ GVfsBackend parent_instance;
+ GVfsMonitor *root_monitor;
+ GMountSpec *mount_spec;
+ GList *files; /* list of NetworkFiles */
+ int idle_tag;
+
+ /* SMB Stuff */
+ gboolean have_smb;
+ char *current_workgroup;
+ GFileMonitor *smb_monitor;
+ GMutex *smb_mount_lock;
+ GVfsJobMount *mount_job;
+
+ /* DNS-SD Stuff */
+ gboolean have_dnssd;
+ NetworkLocalSetting local_setting;
+ char *extra_domains;
+ GFileMonitor *dnssd_monitor;
+
+ /* Icons */
+ GIcon *workgroup_icon; /* GThemedIcon = "network-workgroup" */
+ GIcon *server_icon; /* GThemedIcon = "network-server" */
+};
+
+typedef struct _GVfsBackendNetwork GVfsBackendNetwork;
+
+G_DEFINE_TYPE (GVfsBackendNetwork, g_vfs_backend_network, G_VFS_TYPE_BACKEND);
+
+static NetworkFile *
+network_file_new (const char *file_name,
+ const char *display_name,
+ const char *target_uri,
+ GIcon *icon)
+{
+ NetworkFile *file;
+
+ file = g_slice_new0 (NetworkFile);
+
+ file->file_name = g_strdup (file_name);
+ file->display_name = g_strdup (display_name);
+ file->target_uri = g_strdup (target_uri);
+ file->icon = g_object_ref (icon);
+
+ return file;
+}
+
+static void
+network_file_free (NetworkFile *file)
+{
+ g_free (file->file_name);
+ g_free (file->display_name);
+ g_free (file->target_uri);
+
+ if (file->icon)
+ g_object_unref (file->icon);
+
+ g_slice_free (NetworkFile, file);
+}
+
+/* Assumes file_name is equal and compares for
+ metadata changes */
+static gboolean
+network_file_equal (NetworkFile *a,
+ NetworkFile *b)
+{
+ if (!g_icon_equal (a->icon, b->icon))
+ return FALSE;
+
+ if ((a->display_name != NULL && b->display_name == NULL) ||
+ (a->display_name == NULL && b->display_name != NULL))
+ return FALSE;
+
+ if ((a->display_name != NULL && b->display_name != NULL) &&
+ strcmp (a->display_name, b->display_name) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+sort_file_by_file_name (NetworkFile *a, NetworkFile *b)
+{
+ return strcmp (a->file_name, b->file_name);
+}
+
+static NetworkLocalSetting
+parse_network_local_setting (const char *setting)
+{
+ if (setting == NULL)
+ return NETWORK_LOCAL_DISABLED;
+ if (strcmp (setting, "separate") == 0)
+ return NETWORK_LOCAL_SEPARATE;
+ if (strcmp (setting, "merged") == 0)
+ return NETWORK_LOCAL_MERGED;
+ return NETWORK_LOCAL_DISABLED;
+}
+
+static void
+update_from_files (GVfsBackendNetwork *backend,
+ GList *files)
+{
+ GList *old_files;
+ GList *oldl, *newl;
+ char *file_name;
+ NetworkFile *old, *new;
+ int cmp;
+
+ old_files = backend->files;
+ backend->files = g_list_sort (files, (GCompareFunc)sort_file_by_file_name);
+
+ /* Generate change events */
+ oldl = old_files;
+ newl = backend->files;
+ while (oldl != NULL || newl != NULL)
+ {
+ if (oldl == NULL)
+ {
+ cmp = 1;
+ new = newl->data;
+ old = NULL;
+ }
+ else if (newl == NULL)
+ {
+ cmp = -1;
+ new = NULL;
+ old = oldl->data;
+ }
+ else
+ {
+ new = newl->data;
+ old = oldl->data;
+ cmp = sort_file_by_file_name (old, new);
+ }
+
+ if (cmp == 0)
+ {
+ if (!network_file_equal (old, new))
+ {
+ file_name = g_strconcat ("/", new->file_name, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_CHANGED,
+ file_name,
+ NULL);
+ g_free (file_name);
+ }
+
+ oldl = oldl->next;
+ newl = newl->next;
+ }
+ else if (cmp < 0)
+ {
+ file_name = g_strconcat ("/", old->file_name, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_DELETED,
+ file_name,
+ NULL);
+ g_free (file_name);
+ oldl = oldl->next;
+ }
+ else
+ {
+ file_name = g_strconcat ("/", new->file_name, NULL);
+ g_vfs_monitor_emit_event (backend->root_monitor,
+ G_FILE_MONITOR_EVENT_CREATED,
+ file_name,
+ NULL);
+ g_free (file_name);
+ newl = newl->next;
+ }
+ }
+
+ g_list_foreach (old_files, (GFunc)network_file_free, NULL);
+}
+
+static void
+notify_dnssd_local_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
+ GFileMonitorEvent event_type, gpointer user_data);
+
+static void
+notify_smb_files_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
+ GFileMonitorEvent event_type, gpointer user_data);
+
+static void
+recompute_files (GVfsBackendNetwork *backend)
+{
+ GFile *server_file;
+ GFileEnumerator *enumer;
+ GFileInfo *info;
+ GFileMonitor *monitor;
+ GError *error;
+ GList *files;
+ NetworkFile *file;
+ char *file_name, *link_uri;
+
+ files = NULL;
+ error = NULL;
+ if (backend->have_smb)
+ {
+ char *workgroup;
+
+ /* smb:/// root link */
+ file = network_file_new ("smb-root", _("Windows Network"),
+ "smb:///", backend->workgroup_icon);
+ files = g_list_prepend (files, file);
+
+ if (backend->current_workgroup == NULL ||
+ backend->current_workgroup[0] == 0)
+ workgroup = g_strconcat ("smb://", DEFAULT_WORKGROUP_NAME, "/", NULL);
+ else
+ workgroup = g_strconcat ("smb://", backend->current_workgroup, "/", NULL);
+
+ server_file = g_file_new_for_uri (workgroup);
+
+ /* recreate monitor if our workgroup changed or we don't have a monitor */
+ if (backend->smb_monitor == NULL)
+ {
+ monitor = g_file_monitor_directory (server_file, G_FILE_MONITOR_NONE, NULL, &error);
+ if (monitor)
+ {
+ g_signal_connect (monitor, "changed",
+ (GCallback)notify_smb_files_changed, (gpointer)backend);
+ /* takes ref */
+ backend->smb_monitor = monitor;
+ }
+ else
+ {
+ char *uri = g_file_get_uri (server_file);
+ g_warning ("Couldn't create directory monitor on %s. Error: %s",
+ uri, error->message);
+ g_free (uri);
+ g_clear_error (&error);
+ }
+ }
+
+ /* children of current workgroup */
+ enumer = g_file_enumerate_children (server_file,
+ NETWORK_FILE_ATTRIBUTES,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+
+ if (enumer != NULL)
+ {
+ info = g_file_enumerator_next_file (enumer, NULL, NULL);
+ while (info != NULL)
+ {
+ file_name = g_strconcat("smb-server-", g_file_info_get_name (info), NULL);
+ link_uri = g_strconcat("smb://", g_file_info_get_name (info), "/", NULL);
+ file = network_file_new (file_name,
+ g_file_info_get_display_name (info),
+ link_uri,
+ backend->server_icon);
+ files = g_list_prepend (files, file);
+
+ g_free (link_uri);
+ g_free (file_name);
+ g_object_unref (info);
+ info = g_file_enumerator_next_file (enumer, NULL, NULL);
+ }
+ g_file_enumerator_close (enumer, NULL, NULL);
+ g_object_unref (enumer);
+ }
+
+ g_object_unref (server_file);
+
+ g_free (workgroup);
+ }
+
+ if (backend->have_dnssd)
+ {
+ server_file = g_file_new_for_uri ("dns-sd://local/");
+ /* create directory monitor if we haven't already */
+ if (backend->dnssd_monitor == NULL)
+ {
+ monitor = g_file_monitor_directory (server_file, G_FILE_MONITOR_NONE, NULL, &error);
+ if (monitor)
+ {
+ g_signal_connect (monitor, "changed",
+ (GCallback)notify_dnssd_local_changed, (gpointer)backend);
+ /* takes ref */
+ backend->dnssd_monitor = monitor;
+ }
+ else
+ {
+ char *uri = g_file_get_uri(server_file);
+ g_warning ("Couldn't create directory monitor on %s. Error: %s",
+ uri, error->message);
+ g_free (uri);
+ g_clear_error (&error);
+ }
+ }
+
+ if (backend->local_setting == NETWORK_LOCAL_MERGED)
+ {
+ /* "merged": add local domains to network:/// */
+ enumer = g_file_enumerate_children (server_file,
+ NETWORK_FILE_ATTRIBUTES,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ if (enumer != NULL)
+ {
+ info = g_file_enumerator_next_file (enumer, NULL, NULL);
+ while (info != NULL)
+ {
+ file_name = g_strconcat("dnssd-domain-", g_file_info_get_name (info), NULL);
+ link_uri = g_strdup(g_file_info_get_attribute_string (info,
+ "standard::target-uri"));
+ file = network_file_new (file_name,
+ g_file_info_get_display_name (info),
+ link_uri,
+ backend->server_icon);
+ files = g_list_prepend (files, file);
+
+ g_free (link_uri);
+ g_free (file_name);
+ g_object_unref (info);
+ info = g_file_enumerator_next_file (enumer, NULL, NULL);
+ }
+ }
+
+ g_file_enumerator_close (enumer, NULL, NULL);
+ g_object_unref (enumer);
+ }
+ else
+ {
+ /* "separate": a link to dns-sd://local/ */
+ file = network_file_new ("dnssd-local", _("Local Network"),
+ "dns-sd://local/", backend->workgroup_icon);
+ files = g_list_prepend (files, file);
+ }
+
+ g_object_unref (server_file);
+
+ /* If gconf setting "/system/dns_sd/extra_domains" is set to a list of domains:
+ * links to dns-sd://$domain/ */
+ if (backend->extra_domains != NULL &&
+ backend->extra_domains[0] != 0)
+ {
+ char **domains;
+ int i;
+ domains = g_strsplit (backend->extra_domains, ",", 0);
+ for (i=0; domains[i] != NULL; i++)
+ {
+ file_name = g_strconcat("dnssd-domain-", domains[i], NULL);
+ link_uri = g_strconcat("dns-sd://", domains[i], "/", NULL);
+ file = network_file_new (file_name,
+ domains[i],
+ link_uri,
+ backend->workgroup_icon);
+ files = g_list_prepend (files, file);
+ g_free (link_uri);
+ g_free (file_name);
+ }
+ g_strfreev (domains);
+ }
+ }
+
+ update_from_files (backend, files);
+}
+
+static gboolean
+idle_add_recompute (GVfsBackendNetwork *backend)
+{
+ backend->idle_tag = 0;
+
+ recompute_files (backend);
+
+ return FALSE;
+}
+
+static void
+mount_smb_done_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(user_data);
+ GError *error = NULL;
+
+ g_file_mount_enclosing_volume_finish (G_FILE (object), res, &error);
+
+ if (error)
+ g_error_free (error);
+
+ recompute_files (backend);
+
+ /* We've been spawned from try_mount */
+ if (backend->mount_job)
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (backend->mount_job));
+ g_object_unref (backend->mount_job);
+ }
+ g_mutex_unlock (backend->smb_mount_lock);
+}
+
+static void
+remount_smb (GVfsBackendNetwork *backend, GVfsJobMount *job)
+{
+ GFile *file;
+ char *workgroup;
+
+ if (! g_mutex_trylock (backend->smb_mount_lock))
+ /* Do nothing when the mount operation is already active */
+ return;
+
+ backend->mount_job = job ? g_object_ref (job) : NULL;
+
+ if (backend->current_workgroup == NULL ||
+ backend->current_workgroup[0] == 0)
+ workgroup = g_strconcat ("smb://", DEFAULT_WORKGROUP_NAME, "/", NULL);
+ else
+ workgroup = g_strconcat ("smb://", backend->current_workgroup, "/", NULL);
+
+ file = g_file_new_for_uri (workgroup);
+
+ g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE,
+ NULL, NULL, mount_smb_done_cb, backend);
+ g_free (workgroup);
+ g_object_unref (file);
+}
+
+static void
+notify_smb_files_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
+ GFileMonitorEvent event_type, gpointer user_data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(user_data);
+
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+ break;
+ case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
+ case G_FILE_MONITOR_EVENT_UNMOUNTED:
+ /* in either event, our smb backend is/will be gone. */
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+
+ /* stop monitoring as the backend's gone. */
+ if (backend->smb_monitor)
+ {
+ g_file_monitor_cancel (backend->smb_monitor);
+ g_object_unref (backend->smb_monitor);
+ backend->smb_monitor = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+notify_dnssd_local_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
+ GFileMonitorEvent event_type, gpointer user_data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(user_data);
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+ break;
+ case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
+ case G_FILE_MONITOR_EVENT_UNMOUNTED:
+ /* in either event, our dns-sd backend is/will be gone. */
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+ /* stop monitoring as the backend's gone. */
+ g_file_monitor_cancel (backend->dnssd_monitor);
+ g_object_unref (backend->dnssd_monitor);
+ backend->dnssd_monitor = NULL;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+notify_gconf_dnssd_domains_changed (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(data);
+ char *extra_domains;
+ extra_domains = gconf_client_get_string (client,
+ PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS, NULL);
+
+ g_free (backend->extra_domains);
+ backend->extra_domains = extra_domains;
+
+ /* don't re-issue recomputes if we've already queued one. */
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+}
+
+static void
+notify_gconf_dnssd_display_local_changed (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(data);
+ char *display_local;
+
+ display_local = gconf_client_get_string (client,
+ PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL, NULL);
+
+ backend->local_setting = parse_network_local_setting (display_local);
+ g_free (display_local);
+
+ /* don't re-issue recomputes if we've already queued one. */
+ if (backend->idle_tag == 0)
+ backend->idle_tag = g_idle_add ((GSourceFunc)idle_add_recompute, backend);
+}
+
+static void
+notify_gconf_smb_workgroup_changed (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(data);
+ char *current_workgroup;
+
+ current_workgroup = gconf_client_get_string (client,
+ PATH_GCONF_GVFS_SMB_WORKGROUP, NULL);
+
+ g_free (backend->current_workgroup);
+ backend->current_workgroup = current_workgroup;
+
+ /* cancel the smb monitor */
+ if (backend->smb_monitor)
+ {
+ g_signal_handlers_disconnect_by_func (backend->smb_monitor,
+ notify_smb_files_changed,
+ backend->smb_monitor);
+ g_file_monitor_cancel (backend->smb_monitor);
+ g_object_unref (backend->smb_monitor);
+ backend->smb_monitor = NULL;
+ }
+
+ remount_smb (backend, NULL);
+}
+
+static NetworkFile *
+lookup_network_file (GVfsBackendNetwork *backend,
+ GVfsJob *job,
+ const char *file_name)
+{
+ GList *l;
+ NetworkFile *file;
+
+ if (*file_name != '/')
+ goto out;
+
+ while (*file_name == '/')
+ file_name++;
+
+ if (*file_name == 0)
+ return &root;
+
+ if (strchr (file_name, '/') != NULL)
+ goto out;
+
+ for (l = backend->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+ if (strcmp (file->file_name, file_name) == 0)
+ return file;
+ }
+
+ out:
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+
+ return NULL;
+}
+
+
+static void
+file_info_from_file (NetworkFile *file,
+ GFileInfo *info)
+{
+ g_return_if_fail (file != NULL || info != NULL);
+
+ g_file_info_set_name (info, file->file_name);
+ g_file_info_set_display_name (info, file->display_name);
+
+ if (file->icon)
+ g_file_info_set_icon (info, file->icon);
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT);
+ g_file_info_set_size (info, 0);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ file->target_uri);
+}
+
+/* Backend Functions */
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *file_name,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ NetworkFile *file;
+ GList *l;
+ GFileInfo *info;
+ file = lookup_network_file (G_VFS_BACKEND_NETWORK (backend),
+ G_VFS_JOB (job), file_name);
+
+ if (file != &root)
+ {
+ if (file != NULL)
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_DIRECTORY,
+ _("The file is not a directory"));
+ return TRUE;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB(job));
+
+ /* Enumerate root */
+ for (l = G_VFS_BACKEND_NETWORK (backend)->files; l != NULL; l = l->next)
+ {
+ file = l->data;
+ info = g_file_info_new ();
+ file_info_from_file (file, info);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ g_vfs_job_enumerate_done (job);
+
+ return TRUE;
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *file_name,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ NetworkFile *file;
+
+ file = lookup_network_file (G_VFS_BACKEND_NETWORK (backend),
+ G_VFS_JOB (job), file_name);
+
+ if (file == &root)
+ {
+ GIcon *icon;
+ g_file_info_set_name (info, "/");
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_display_name (info, _("Network"));
+ icon = g_themed_icon_new ("network-workgroup");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
+ g_file_info_set_content_type (info, "inode/directory");
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else if (file != NULL)
+ {
+ file_info_from_file (file, info);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendNetwork *network_backend = G_VFS_BACKEND_NETWORK (backend);
+
+ network_backend->root_monitor = g_vfs_monitor_new (backend);
+
+ if (network_backend->have_smb)
+ {
+ remount_smb (network_backend, job);
+ }
+ else
+ {
+ recompute_files (network_backend);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+/* handles both file and dir monitors
+ * for now we only fire events on the root directory.
+ * are individual file monitors needed for this backend?
+ */
+static gboolean
+try_create_monitor (GVfsBackend *backend,
+ GVfsJobCreateMonitor *job,
+ const char *file_name,
+ GFileMonitorFlags flags)
+{
+ NetworkFile *file;
+ GVfsBackendNetwork *network_backend;
+
+ network_backend = G_VFS_BACKEND_NETWORK (backend);
+
+ file = lookup_network_file (network_backend, G_VFS_JOB (job), file_name);
+
+ if (file != &root)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Can't monitor file or directory."));
+ return TRUE;
+ }
+
+ g_vfs_job_create_monitor_set_monitor (job, network_backend->root_monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_network_init (GVfsBackendNetwork *network_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (network_backend);
+ GMountSpec *mount_spec;
+ GConfClient *gconf_client;
+ char *display_local, *extra_domains;
+ char *current_workgroup;
+ const char * const* supported_vfs;
+ int i;
+
+ network_backend->smb_mount_lock = g_mutex_new ();
+
+ supported_vfs = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());
+
+ network_backend->have_smb = FALSE;
+ network_backend->have_dnssd = FALSE;
+ for (i=0; supported_vfs[i]!=NULL; i++)
+ {
+ if (strcmp(supported_vfs[i], "smb") == 0)
+ network_backend->have_smb = TRUE;
+
+ if (strcmp(supported_vfs[i], "dns-sd") == 0)
+ network_backend->have_dnssd = TRUE;
+ }
+
+ gconf_client = gconf_client_get_default ();
+
+ if (network_backend->have_smb)
+ {
+ gconf_client_add_dir (gconf_client, PATH_GCONF_GVFS_SMB,
+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ current_workgroup = gconf_client_get_string (gconf_client,
+ PATH_GCONF_GVFS_SMB_WORKGROUP, NULL);
+
+ if (current_workgroup == NULL ||
+ current_workgroup[0] == 0)
+ /* it's okay if current_workgroup is null here,
+ * it's checked before the NetworkFile is added anyway. */
+ network_backend->current_workgroup = NULL;
+ else
+ network_backend->current_workgroup = current_workgroup;
+
+ gconf_client_notify_add (gconf_client, PATH_GCONF_GVFS_SMB_WORKGROUP,
+ notify_gconf_smb_workgroup_changed, network_backend, NULL, NULL);
+
+ }
+
+ if (network_backend->have_dnssd)
+ {
+ gconf_client_add_dir (gconf_client, PATH_GCONF_GVFS_DNS_SD,
+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+ display_local = gconf_client_get_string (gconf_client,
+ PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL, NULL);
+ extra_domains = gconf_client_get_string (gconf_client,
+ PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS, NULL);
+
+ if (display_local != NULL && display_local[0] != 0)
+ network_backend->local_setting = parse_network_local_setting (display_local);
+
+ g_free (display_local);
+ network_backend->extra_domains = extra_domains;
+
+ gconf_client_notify_add (gconf_client, PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS,
+ notify_gconf_dnssd_domains_changed, network_backend, NULL, NULL);
+
+ gconf_client_notify_add (gconf_client, PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL,
+ notify_gconf_dnssd_display_local_changed, network_backend, NULL, NULL);
+
+ }
+
+ g_object_unref (gconf_client);
+
+ g_vfs_backend_set_display_name (backend, _("Network"));
+ g_vfs_backend_set_stable_name (backend, _("Network"));
+ g_vfs_backend_set_icon_name (backend, "network-workgroup");
+ g_vfs_backend_set_user_visible (backend, FALSE);
+
+ mount_spec = g_mount_spec_new ("network");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ network_backend->mount_spec = mount_spec;
+
+ network_backend->workgroup_icon = g_themed_icon_new ("network-workgroup");
+ network_backend->server_icon = g_themed_icon_new ("network-server");
+}
+
+static void
+g_vfs_backend_network_finalize (GObject *object)
+{
+ GVfsBackendNetwork *backend;
+ backend = G_VFS_BACKEND_NETWORK (object);
+
+ g_mutex_free (backend->smb_mount_lock);
+ g_mount_spec_unref (backend->mount_spec);
+ g_object_unref (backend->root_monitor);
+ g_object_unref (backend->workgroup_icon);
+ g_object_unref (backend->server_icon);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_network_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_network_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_network_class_init (GVfsBackendNetworkClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_network_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_create_dir_monitor = try_create_monitor;
+ backend_class->try_create_file_monitor = try_create_monitor;
+}
+
+void
+g_vfs_network_daemon_init (void)
+{
+ /* Translators: this is the friendly name of the 'network://' backend that
+ * shows computers in your local network. */
+ g_set_application_name (_("Network Location Monitor"));
+}
+
diff --git a/trunk/daemon/gvfsbackendnetwork.h b/trunk/daemon/gvfsbackendnetwork.h
new file mode 100644
index 00000000..8acbfeef
--- /dev/null
+++ b/trunk/daemon/gvfsbackendnetwork.h
@@ -0,0 +1,55 @@
+/* gvfs-backend-network.h - GIO - GLib Input, Output and Streaming Library
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Alexander Larsson <alexl@redhat.com>
+ * Andrew Walton <awalton@svn.gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_NETWORK_H__
+#define __G_VFS_BACKEND_NETWORK_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_NETWORK (g_vfs_backend_network_get_type ())
+#define G_VFS_BACKEND_NETWORK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetwork))
+#define G_VFS_BACKEND_NETWORK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetworkClass))
+#define G_VFS_IS_BACKEND_NETWORK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_NETWORK))
+#define G_VFS_IS_BACKEND_NETWORK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_NETWORK))
+#define G_VFS_BACKEND_NETWORK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetworkClass))
+
+typedef struct _GVfsBackendNetworkClass GVfsBackendNetworkClass;
+
+struct _GVfsBackendNetworkClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_network_get_type (void) G_GNUC_CONST;
+
+#define BACKEND_SETUP_FUNC g_vfs_network_daemon_init
+void g_vfs_network_daemon_init (void);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_NETWORK_H__ */
diff --git a/trunk/daemon/gvfsbackendobexftp-cap-parser.c b/trunk/daemon/gvfsbackendobexftp-cap-parser.c
new file mode 100644
index 00000000..183195e7
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp-cap-parser.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2004-2005 Nokia Corporation.
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <expat.h>
+
+#include "gvfsbackendobexftp-cap-parser.h"
+
+#define d(x)
+
+struct _OvuCaps {
+ GList *memory_entries;
+
+ /* FIXME: Add "Services" and "Inbox" data here later. */
+};
+
+struct _OvuCapsMemory {
+ gchar *type;
+ goffset free;
+ goffset used;
+ guint has_free : 1;
+ guint has_used : 1;
+ guint case_sensitive : 1;
+};
+
+typedef enum {
+ PARSER_STATE_INVALID,
+
+ PARSER_STATE_START,
+ PARSER_STATE_CAPABILITY,
+
+ PARSER_STATE_GENERAL,
+
+ PARSER_STATE_MEMORY,
+ PARSER_STATE_MEMORY_TYPE,
+ PARSER_STATE_MEMORY_LOCATION,
+ PARSER_STATE_MEMORY_FREE,
+ PARSER_STATE_MEMORY_USED,
+ PARSER_STATE_MEMORY_SHARED,
+ PARSER_STATE_MEMORY_FILESIZE,
+ PARSER_STATE_MEMORY_FOLDERSIZE,
+ PARSER_STATE_MEMORY_FILELEN,
+ PARSER_STATE_MEMORY_FOLDERLEN,
+ PARSER_STATE_MEMORY_CASE,
+ PARSER_STATE_MEMORY_EXT,
+
+ PARSER_STATE_INBOX,
+ PARSER_STATE_SERVICE,
+
+ PARSER_STATE_SKIP
+} ParserState;
+
+
+typedef struct {
+ GList *state;
+
+ GList *memory_entries;
+
+ gchar *memory_type;
+ goffset memory_free;
+ goffset memory_used;
+ gboolean memory_has_free;
+ gboolean memory_has_used;
+ gboolean memory_case_sensitive;
+
+ GError **error;
+} ParserData;
+
+static void cap_parser_start_node_cb (void *user_data,
+ const char *node_name,
+ const char **attr);
+
+static void cap_parser_end_node_cb (void *user_data,
+ const char *node_name);
+static void cap_parser_text_cb (void *user_data,
+ const XML_Char *s,
+ int len);
+static XML_Parser
+cap_parser_create_parser (ParserData *data);
+
+
+static void
+cap_parser_push_state (ParserData *data, ParserState state)
+{
+ data->state = g_list_prepend (data->state,
+ GINT_TO_POINTER (state));
+}
+
+static ParserState
+cap_parser_pop_state (ParserData *data)
+{
+ ParserState state;
+
+ if (!data->state) {
+ return PARSER_STATE_INVALID;
+ }
+
+ state = GPOINTER_TO_INT (data->state->data);
+ data->state = g_list_delete_link (data->state, data->state);
+
+ return state;
+}
+
+static ParserState
+cap_parser_peek_state (ParserData *data)
+{
+ if (!data->state) {
+ return PARSER_STATE_START;
+ }
+
+ return GPOINTER_TO_INT (data->state->data);
+}
+
+static const char *
+cap_parser_get_attribute_value (const char *name, const char **attr)
+{
+ gint i = 0;
+
+ while (attr[i]) {
+ if (strcmp (name, attr[i]) == 0) {
+ return attr[i + 1];
+ }
+ i += 2;
+ }
+
+ return "";
+}
+
+static void
+cap_parser_start_node_cb (void *user_data,
+ const char *node_name,
+ const char **attr)
+{
+ ParserData *data;
+ ParserState state;
+ const gchar *version;
+
+ data = (ParserData *) user_data;
+
+ state = cap_parser_peek_state (data);
+
+ switch (state) {
+ case PARSER_STATE_START:
+ if (strcmp (node_name, "Capability") != 0) {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Outermost element must be a <Capability>, not <%s>",
+ node_name);
+ return;
+ }
+
+ version = cap_parser_get_attribute_value ("version", attr);
+ /* Assume an empty version is fine */
+ if (strcmp (version, "1.0") != 0 && version[0] != '\0') {
+ g_warning ("Version expected is '1.0', not '%s'\n", version);
+ }
+
+ cap_parser_push_state (data, PARSER_STATE_CAPABILITY);
+ break;
+
+ case PARSER_STATE_CAPABILITY:
+ if (strcmp (node_name, "General") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_GENERAL);
+ }
+ else if (strcmp (node_name, "Inbox") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_INBOX);
+ }
+ else if (strcmp (node_name, "Service") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_SERVICE);
+ } else {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Don't expect node '%s' as child of 'Cap'",
+ node_name);
+ return;
+ }
+ break;
+
+ case PARSER_STATE_GENERAL:
+ if (strcmp (node_name, "Memory") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY);
+ }
+ else if (strcmp (node_name, "Manufacturer") == 0 ||
+ strcmp (node_name, "Model") == 0 ||
+ strcmp (node_name, "SN") == 0 ||
+ strcmp (node_name, "OEM") == 0 ||
+ strcmp (node_name, "SW") == 0 ||
+ strcmp (node_name, "FW") == 0 ||
+ strcmp (node_name, "HW") == 0 ||
+ strcmp (node_name, "Language") == 0 ||
+ strcmp (node_name, "Ext") == 0) {
+
+ /* Skip these for now. */
+ cap_parser_push_state (data, PARSER_STATE_SKIP);
+ } else {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Don't expect node '%s' as child of 'General'",
+ node_name);
+ return;
+ }
+
+ break;
+
+ case PARSER_STATE_MEMORY:
+ if (strcmp (node_name, "MemType") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_TYPE);
+ }
+ else if (strcmp (node_name, "Location") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_LOCATION);
+ }
+ else if (strcmp (node_name, "Free") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_FREE);
+ }
+ else if (strcmp (node_name, "Used") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_USED);
+ }
+ else if (strcmp (node_name, "Shared") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_SHARED);
+ }
+ else if (strcmp (node_name, "FileSize") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_FILESIZE);
+ }
+ else if (strcmp (node_name, "FolderSize") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_FOLDERSIZE);
+ }
+ else if (strcmp (node_name, "FileNLen") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_FILELEN);
+ }
+ else if (strcmp (node_name, "FolderNLen") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_FOLDERLEN);
+ }
+ else if (strcmp (node_name, "CaseSenN") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_CASE);
+ data->memory_case_sensitive = TRUE;
+ }
+ else if (strcmp (node_name, "Ext") == 0) {
+ cap_parser_push_state (data, PARSER_STATE_MEMORY_EXT);
+ } else {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Don't expect node '%s' as child of 'Memory'",
+ node_name);
+ return;
+ }
+ break;
+
+ case PARSER_STATE_INBOX:
+ case PARSER_STATE_SERVICE:
+ /* Skip these for now. */
+ cap_parser_push_state (data, PARSER_STATE_SKIP);
+ break;
+
+ case PARSER_STATE_SKIP:
+ cap_parser_push_state (data, PARSER_STATE_SKIP);
+ break;
+
+ default:
+ g_warning ("Node not handled: '%s'\n", node_name);
+ cap_parser_push_state (data, PARSER_STATE_SKIP);
+ break;
+ }
+}
+
+static void
+cap_parser_reset_memory (ParserData *data)
+{
+ g_free (data->memory_type);
+ data->memory_type = NULL;
+ data->memory_free = 0;
+ data->memory_used = 0;
+ data->memory_has_free = FALSE;
+ data->memory_has_used = FALSE;
+ data->memory_case_sensitive = FALSE;
+}
+
+static void
+cap_parser_end_node_cb (void *user_data, const char *node_name)
+{
+ ParserData *data;
+ ParserState state;
+ OvuCapsMemory *memory;
+
+ data = (ParserData *) user_data;
+
+ state = cap_parser_pop_state (data);
+
+ switch (state) {
+ case PARSER_STATE_INVALID:
+ return;
+
+ case PARSER_STATE_MEMORY:
+ memory = ovu_caps_memory_new (data->memory_type,
+ data->memory_free,
+ data->memory_used,
+ data->memory_has_free,
+ data->memory_has_used,
+ data->memory_case_sensitive);
+
+ data->memory_entries = g_list_prepend (data->memory_entries,
+ memory);
+ cap_parser_reset_memory (data);
+ break;
+
+ case PARSER_STATE_CAPABILITY:
+ data->memory_entries = g_list_reverse (data->memory_entries);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Parse a long, return -1 if input is not strictly valid or null. */
+static goffset
+parse_long (const gchar *str, gboolean *success)
+{
+ gchar *endptr;
+ glong l;
+
+ *success = TRUE;
+
+ if (!str) {
+ *success = FALSE;
+ return 0;
+ }
+
+ l = strtol (str, &endptr, 10);
+ if (endptr[0] != '\0' || l < 0) {
+ *success = FALSE;
+ l = 0;
+ }
+
+ return l;
+}
+
+static void
+cap_parser_text_cb (void *user_data,
+ const XML_Char *s,
+ int len)
+{
+ ParserData *data;
+ ParserState state;
+ gchar *tmp;
+
+ data = (ParserData *) user_data;
+
+ /* text is not null terminated. */
+ tmp = g_strndup (s, len);
+
+ state = cap_parser_peek_state (data);
+
+ switch (state) {
+ case PARSER_STATE_MEMORY_TYPE:
+ data->memory_type = g_strdup (tmp);
+ break;
+ case PARSER_STATE_MEMORY_FREE:
+ data->memory_free = parse_long (tmp, &data->memory_has_free);
+ break;
+ case PARSER_STATE_MEMORY_USED:
+ data->memory_used = parse_long (tmp, &data->memory_has_used);
+ break;
+
+ default:
+ break;
+ }
+
+ g_free (tmp);
+}
+
+static XML_Parser
+cap_parser_create_parser (ParserData *data)
+{
+ XML_Parser parser;
+
+ parser = XML_ParserCreate (NULL);
+
+ XML_SetElementHandler (parser,
+ cap_parser_start_node_cb,
+ cap_parser_end_node_cb);
+
+ XML_SetCharacterDataHandler (parser, cap_parser_text_cb);
+
+ XML_SetUserData (parser, data);
+
+ return parser;
+}
+
+static void
+cap_parser_free (ParserData *data, gboolean free_data)
+{
+ cap_parser_reset_memory (data);
+
+ if (free_data) {
+ g_list_foreach (data->memory_entries,
+ (GFunc) ovu_caps_memory_free, NULL);
+ }
+
+ g_free (data);
+}
+
+OvuCaps *
+ovu_caps_parser_parse (const gchar *buf,
+ gint len,
+ GError **error)
+{
+ ParserData *data;
+ XML_Parser parser;
+ OvuCaps *caps;
+
+ data = g_new0 (ParserData, 1);
+
+ data->error = error;
+ parser = cap_parser_create_parser (data);
+
+ if (XML_Parse (parser, buf, len, TRUE) == 0) {
+ caps = NULL;
+
+ if (*error == NULL) {
+ g_set_error_literal (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Couldn't parse the incoming data");
+ }
+
+ cap_parser_free (data, TRUE);
+ } else {
+ caps = g_new0 (OvuCaps, 1);
+ caps->memory_entries = data->memory_entries;
+
+ cap_parser_free (data, FALSE);
+ }
+
+ XML_ParserFree (parser);
+
+ return caps;
+}
+
+OvuCapsMemory *
+ovu_caps_memory_new (const gchar *type,
+ goffset free,
+ goffset used,
+ gboolean has_free,
+ gboolean has_used,
+ gboolean case_sensitive)
+{
+ OvuCapsMemory *memory;
+
+ memory = g_new0 (OvuCapsMemory, 1);
+
+ memory->type = g_strdup (type);
+ memory->free = free;
+ memory->used = used;
+ memory->has_free = has_free;
+ memory->has_used = has_used;
+ memory->case_sensitive = case_sensitive;
+
+ return memory;
+}
+
+void
+ovu_caps_memory_free (OvuCapsMemory *memory)
+{
+ g_free (memory->type);
+ g_free (memory);
+}
+
+gboolean
+ovu_caps_memory_equal (OvuCapsMemory *m1, OvuCapsMemory *m2)
+{
+ if (strcmp (m1->type, m2->type) != 0) {
+ d(g_print ("type mismatch: %s %s\n",
+ m1->type, m2->type));
+ return FALSE;
+ }
+
+ if (m1->free != m2->free) {
+ d(g_print ("free mismatch: %d %d\n",
+ (int) m1->free, (int) m2->free));
+ return FALSE;
+ }
+
+ if (m1->used != m2->used) {
+ d(g_print ("used mismatch: %d %d\n",
+ (int) m1->used, (int) m2->used));
+ return FALSE;
+ }
+
+ if (m1->case_sensitive != m2->case_sensitive) {
+ d(g_print ("case mismatch: %d %d\n",
+ m1->case_sensitive,
+ m2->case_sensitive));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+ovu_caps_free (OvuCaps *caps)
+{
+ g_list_foreach (caps->memory_entries,
+ (GFunc) ovu_caps_memory_free, NULL);
+
+ g_list_free (caps->memory_entries);
+
+ g_free (caps);
+}
+
+GList *
+ovu_caps_get_memory_entries (OvuCaps *caps)
+{
+ g_return_val_if_fail (caps != NULL, NULL);
+
+ return caps->memory_entries;
+}
+
+OvuCapsMemory *
+ovu_caps_get_memory_type (OvuCaps *caps,
+ const gchar *mem_type)
+{
+ GList *tmp;
+
+ g_return_val_if_fail (caps != NULL, NULL);
+
+ for (tmp = caps->memory_entries; tmp != NULL; tmp = tmp->next) {
+ OvuCapsMemory *memory = tmp->data;
+
+ /* treat a NULL memory type as matching anything */
+ if (mem_type == NULL || (memory->type != NULL &&
+ !strcmp(mem_type, memory->type)))
+ return memory;
+ }
+ return NULL;
+}
+
+const gchar *
+ovu_caps_memory_get_type (OvuCapsMemory *memory)
+{
+ return memory->type;
+}
+
+goffset
+ovu_caps_memory_get_used (OvuCapsMemory *memory)
+{
+ return memory->used;
+}
+
+goffset
+ovu_caps_memory_get_free (OvuCapsMemory *memory)
+{
+ return memory->free;
+}
+
+gboolean
+ovu_caps_memory_has_used (OvuCapsMemory *memory)
+{
+ return memory->has_used;
+}
+
+gboolean
+ovu_caps_memory_has_free (OvuCapsMemory *memory)
+{
+ return memory->has_free;
+}
+
+gboolean
+ovu_caps_memory_get_case_sensitive (OvuCapsMemory *memory)
+{
+ return memory->case_sensitive;
+}
diff --git a/trunk/daemon/gvfsbackendobexftp-cap-parser.h b/trunk/daemon/gvfsbackendobexftp-cap-parser.h
new file mode 100644
index 00000000..bfa58ca2
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp-cap-parser.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+#ifndef __OVU_CAP_PARSER_H__
+#define __OVU_CAP_PARSER_H__
+
+#include <glib.h>
+
+typedef struct _OvuCaps OvuCaps;
+typedef struct _OvuCapsMemory OvuCapsMemory;
+
+OvuCaps * ovu_caps_parser_parse (const gchar *buf,
+ gint len,
+ GError **error);
+
+GList * ovu_caps_get_memory_entries (OvuCaps *caps);
+OvuCapsMemory *ovu_caps_get_memory_type (OvuCaps *caps,
+ const gchar *mem_type);
+void ovu_caps_free (OvuCaps *caps);
+OvuCapsMemory * ovu_caps_memory_new (const gchar *type,
+ goffset free,
+ goffset used,
+ gboolean has_free,
+ gboolean has_used,
+ gboolean case_sensitive);
+void ovu_caps_memory_free (OvuCapsMemory *memory);
+gboolean ovu_caps_memory_equal (OvuCapsMemory *m1,
+ OvuCapsMemory *m2);
+const gchar * ovu_caps_memory_get_type (OvuCapsMemory *memory);
+goffset ovu_caps_memory_get_used (OvuCapsMemory *memory);
+goffset ovu_caps_memory_get_free (OvuCapsMemory *memory);
+gboolean ovu_caps_memory_has_used (OvuCapsMemory *memory);
+gboolean ovu_caps_memory_has_free (OvuCapsMemory *memory);
+gboolean ovu_caps_memory_get_case_sensitive (OvuCapsMemory *memory);
+
+#endif /* __OVU_CAP_PARSER_H__ */
+
diff --git a/trunk/daemon/gvfsbackendobexftp-fl-parser.c b/trunk/daemon/gvfsbackendobexftp-fl-parser.c
new file mode 100644
index 00000000..9c491688
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp-fl-parser.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2004-2005 Nokia Corporation.
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net> (gio port)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <gio/gio.h>
+#include <expat.h>
+
+#include "gvfsbackendobexftp-fl-parser.h"
+
+#define d(x)
+
+typedef struct {
+ GError **error;
+ GList *elements;
+
+ gint depth;
+} ParserData;
+
+/* Static functions declaration */
+static void fl_parser_start_node_cb (void *data,
+ const char *el,
+ const char **attr);
+static void fl_parser_end_node_cb (void *data,
+ const char *el);
+static XML_Parser fl_parser_create_context (ParserData *data);
+static gboolean fl_parser_fill_file_info (GFileInfo *file_info,
+ const char **attr);
+static void fl_parser_free_parser_data (ParserData *data,
+ gboolean free_list);
+
+
+/* Function implementations */
+static void
+fl_parser_start_node_cb (void *user_data,
+ const char *node_name,
+ const char **attr)
+{
+ ParserData *data;
+ GFileInfo *info;
+
+ data = (ParserData *) user_data;
+
+ data->depth++;
+
+ d(g_print ("%d: %s\n", data->depth, node_name));
+
+ if (data->depth > 2) {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Don't expect node '%s' as child of 'file', 'folder' or 'parent-folder'",
+ node_name);
+ return;
+ }
+ else if (data->depth == 1) {
+ if (strcmp (node_name, "folder-listing") != 0) {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Expected 'folder-listing', got '%s'",
+ node_name);
+ return;
+ }
+
+ return;
+ }
+
+ if (strcmp (node_name, "parent-folder") == 0) {
+ /* Just ignore parent-folder items */
+ return;
+ }
+
+ info = g_file_info_new ();
+
+ if (strcmp (node_name, "file") == 0) {
+ g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+ }
+ else if (strcmp (node_name, "folder") == 0) {
+ GIcon *icon;
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
+
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ } else {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ "Unknown element '%s'",
+ node_name);
+ return;
+ }
+
+ if (!fl_parser_fill_file_info (info, attr)) {
+ d(g_print ("Failed to fill GnomeVFSFileInfo from node '%s'\n",
+ node_name));
+ g_object_unref (info);
+ return;
+ }
+
+ if (g_file_info_get_content_type (info) == NULL) {
+ char *mime_type;
+ mime_type = g_content_type_guess (g_file_info_get_name (info), NULL, 0, NULL);
+ g_file_info_set_content_type (info, mime_type);
+ g_free (mime_type);
+ }
+
+ if (g_file_info_get_content_type (info) == NULL) {
+ g_file_info_set_content_type (info, "application/octet-stream");
+ }
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR) {
+ GIcon *icon;
+
+ icon = g_content_type_get_icon (g_file_info_get_content_type (info));
+ if (icon != NULL) {
+ if (G_IS_THEMED_ICON (icon))
+ g_themed_icon_append_name (G_THEMED_ICON (icon), "text-x-generic");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+ }
+
+ /* Permissions on folders in OBEX has different semantics than POSIX.
+ * In POSIX, if a folder is not writable, it means that it's content
+ * can't be removed, whereas in OBEX, it just means that the folder
+ * itself can't be removed. Therefore we must set all folders to RWD and
+ * handle the error when it happens. */
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
+ TRUE);
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ TRUE);
+ }
+
+ data->elements = g_list_prepend (data->elements, info);
+}
+
+static void
+fl_parser_end_node_cb (void *user_data, const char *node_name)
+{
+ ParserData *data;
+
+ data = (ParserData *) user_data;
+
+ data->depth--;
+
+ if (data->depth < 0) {
+ g_set_error (data->error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Closing non-open node '%s'",
+ node_name);
+ return;
+ }
+
+ d(g_print ("%d: /%s\n", data->depth, node_name));
+}
+
+static XML_Parser
+fl_parser_create_context (ParserData *data)
+{
+ XML_Parser parser;
+
+ parser = XML_ParserCreate (NULL);
+
+ XML_SetElementHandler(parser,
+ (XML_StartElementHandler) fl_parser_start_node_cb,
+ (XML_EndElementHandler) fl_parser_end_node_cb);
+ XML_SetUserData (parser, data);
+
+ return parser;
+}
+
+static gboolean
+fl_parser_fill_file_info (GFileInfo *info, const char **attr)
+{
+ gint i;
+
+ for (i = 0; attr[i]; ++i) {
+ const gchar *name;
+ const gchar *value;
+
+ name = attr[i];
+ value = attr[++i];
+
+ if (strcmp (name, "name") == 0) {
+ char *display_name;
+ /* Apparently someone decided it was a good idea
+ * to send name="" mem-type="MMC"
+ */
+ if (!value || strcmp (value, "") == 0) {
+ return FALSE;
+ }
+
+ g_file_info_set_name (info, value);
+ display_name = g_filename_display_name (value);
+ g_file_info_set_display_name (info, display_name);
+ d(g_print ("Name: '%s'\n", display_name));
+ g_free (display_name);
+ }
+ else if (strcmp (name, "size") == 0) {
+ g_file_info_set_size (info, strtoll (value, NULL, 10));
+ d(g_print ("Size: '%"G_GINT64_FORMAT"'\n", g_file_info_get_size (info)));
+ }
+ else if (strcmp (name, "modified") == 0) {
+ GTimeVal time;
+
+ if (g_time_val_from_iso8601 (value, &time) == FALSE)
+ continue;
+ g_file_info_set_modification_time (info, &time);
+ d(g_print ("Modified: '%s' = '%d'\n",
+ value, (int)time.tv_sec));
+ }
+ else if (strcmp (name, "created") == 0) {
+ GTimeVal time;
+
+ if (g_time_val_from_iso8601 (value, &time) == FALSE)
+ continue;
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_CREATED,
+ time.tv_sec);
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_TIME_CREATED_USEC,
+ time.tv_usec);
+ d(g_print ("Created: '%s' = '%d'\n",
+ value, (int)time.tv_sec));
+ }
+ else if (strcmp (name, "accessed") == 0) {
+ GTimeVal time;
+
+ if (g_time_val_from_iso8601 (value, &time) == FALSE)
+ continue;
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_ACCESS,
+ time.tv_sec);
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
+ time.tv_usec);
+ d(g_print ("Accessed: '%s' = '%d'\n",
+ value, (int)time.tv_sec));
+ }
+ else if (strcmp (name, "user-perm") == 0) {
+ /* The permissions don't map well to unix semantics,
+ * since the user is most likely not the same on both
+ * sides. We map the user permissions to "other" on the
+ * local side. D is treated as write, otherwise files
+ * can't be deleted through the module, even if it
+ * should be possible.
+ */
+ if (strstr (value, "R")) {
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
+ TRUE);
+ }
+ if (strstr (value, "W") || strstr (value, "D")) {
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ TRUE);
+ }
+ }
+ else if (strcmp (name, "group-perm") == 0) {
+ /* Ignore for now */
+ d(g_print ("Group permissions: '%s'\n", value));
+ }
+ else if (strcmp (name, "other-perm") == 0) {
+ /* Ignore for now */
+ d(g_print ("Other permissions: '%s'\n", value));
+ }
+ else if (strcmp (name, "owner") == 0) {
+ /* Ignore for now */
+ d(g_print ("Owner: '%s'\n", value));
+ }
+ else if (strcmp (name, "group") == 0) {
+ /* Ignore for now */
+ d(g_print ("Group: '%s'\n", value));
+ }
+ else if (strcmp (name, "type") == 0) {
+ g_file_info_set_content_type (info, value);
+ d(g_print ("Mime-Type: '%s'\n", value));
+ }
+ else if (strcmp (name, "xml:lang") == 0) {
+ d(g_print ("Lang: '%s'\n", value));
+ }
+ else if (strcmp (name, "mem-type") == 0) {
+ guint device;
+
+ if (value == NULL || value[0] == '\0')
+ continue;
+
+ device = om_mem_type_id_from_string (value);
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_UNIX_RDEV,
+ device);
+ d(g_print ("Mem-Type: '%s' (%d)\n",
+ value, device));
+ }
+ else {
+ d(g_print ("Unknown Attribute: %s = %s\n",
+ name, value));
+ }
+ }
+
+ if (g_file_info_get_name (info) == NULL) { /* Required attribute */
+ /* Set error */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+fl_parser_free_parser_data (ParserData *data, gboolean free_list)
+{
+ if (free_list) {
+ g_list_foreach (data->elements, (GFunc) g_object_unref, NULL);
+ g_list_free (data->elements);
+ data->elements = NULL;
+ }
+
+ g_free (data);
+}
+
+gboolean
+gvfsbackendobexftp_fl_parser_parse (const gchar *buf, gint len, GList **elements,
+ GError **error)
+{
+ ParserData *data;
+ XML_Parser parser;
+
+ data = g_new0 (ParserData, 1);
+ data->error = error;
+ data->elements = NULL;
+ data->depth = 0;
+
+ parser = fl_parser_create_context (data);
+ if (!parser) {
+ g_free (data);
+ return FALSE;
+ }
+
+ if (XML_Parse (parser, buf, len, TRUE) == 0) {
+ XML_ParserFree (parser);
+ fl_parser_free_parser_data (data, TRUE);
+
+ if (*error == NULL) {
+ g_set_error_literal (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Couldn't parse the incoming data");
+ }
+ return FALSE;
+ }
+
+ XML_ParserFree (parser);
+
+ *elements = data->elements;
+
+ fl_parser_free_parser_data (data, FALSE);
+
+ return TRUE;
+}
+
+static GPtrArray *mem_types = NULL;
+static GHashTable *mem_types_ht = NULL;
+
+guint
+om_mem_type_id_from_string (const gchar *memtype)
+{
+ guint mem_id;
+ gchar *value;
+
+ if (memtype == NULL || memtype[0] == '\0')
+ return 0;
+
+ if (mem_types_ht != NULL) {
+ mem_id = GPOINTER_TO_UINT (g_hash_table_lookup
+ (mem_types_ht, memtype));
+ if (mem_id != 0)
+ return mem_id;
+ } else {
+ mem_types = g_ptr_array_new ();
+ /* Insert a dummy entry, so that we don't use 0 as a mem_id */
+ g_ptr_array_add (mem_types, NULL);
+ mem_types_ht = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+ value = g_strdup (memtype);
+ mem_id = mem_types->len;
+ g_ptr_array_add (mem_types, value);
+ g_hash_table_insert (mem_types_ht, value, GUINT_TO_POINTER (mem_id));
+ return mem_id;
+}
+
+const gchar *
+om_mem_type_id_to_string (guint mem_id)
+{
+ if (mem_types == NULL || mem_id >= mem_types->len)
+ return NULL;
+ else
+ return g_ptr_array_index (mem_types, mem_id);
+}
diff --git a/trunk/daemon/gvfsbackendobexftp-fl-parser.h b/trunk/daemon/gvfsbackendobexftp-fl-parser.h
new file mode 100644
index 00000000..61303d29
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp-fl-parser.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004 Nokia Corporation.
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net> (gio port)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+#ifndef __GVFSBACKENDOBEXFTP_FL_PARSER_H__
+#define __GVFSBACKENDOBEXFTP_FL_PARSER_H__
+
+#include <glib.h>
+
+gboolean gvfsbackendobexftp_fl_parser_parse (const gchar *buf,
+ gint len,
+ GList **elements,
+ GError **error);
+void gvfsbackendobexftp_fl_parser_free_element_list (GSList *elements);
+
+
+
+guint om_mem_type_id_from_string (const gchar *memtype);
+const gchar *om_mem_type_id_to_string (guint mem_id);
+
+#endif /* __GVFSBACKENDOBEXFTP_FL_PARSER_H__ */
diff --git a/trunk/daemon/gvfsbackendobexftp.c b/trunk/daemon/gvfsbackendobexftp.c
new file mode 100644
index 00000000..f3b1517f
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp.c
@@ -0,0 +1,2116 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Bastien Nocera <hadess@hadess.net>
+ * Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <libhal.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <bluetooth/bluetooth.h>
+
+#include "gvfsbackendobexftp.h"
+#include "gvfsbackendobexftp-fl-parser.h"
+#include "gvfsbackendobexftp-cap-parser.h"
+#include "obexftp-marshal.h"
+
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobmount.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+
+#define BDADDR_LEN 17
+
+#define ASYNC_SUCCESS 2
+#define ASYNC_RUNNING 1
+#define ASYNC_PENDING 0
+#define ASYNC_ERROR -1
+
+#define CACHE_LIFESPAN 3
+
+struct _GVfsBackendObexftp
+{
+ GVfsBackend parent_instance;
+
+ char *display_name;
+ char *bdaddr;
+ char *icon_name;
+ gint usbintfnum;
+
+ DBusGConnection *connection;
+ DBusGProxy *manager_proxy;
+ DBusGProxy *session_proxy;
+
+ /* Use for the async notifications and errors */
+ GCond *cond;
+ GMutex *mutex;
+ int status;
+ gboolean doing_io;
+ GError *error;
+
+ /* Folders listing cache */
+ char *files_listing;
+ char *directory;
+ time_t time_captured;
+};
+
+typedef struct {
+ char *source;
+ goffset size;
+ int fd;
+} ObexFTPOpenHandle;
+
+G_DEFINE_TYPE (GVfsBackendObexftp, g_vfs_backend_obexftp, G_VFS_TYPE_BACKEND);
+
+static void session_connect_error_cb (DBusGProxy *proxy,
+ const char *session_object,
+ const gchar *error_name,
+ const gchar *error_message,
+ gpointer user_data);
+static void session_connected_cb (DBusGProxy *proxy,
+ const char *session_object,
+ gpointer user_data);
+
+/* Parse USB paths from do_mount(), or obex-data-server */
+static gboolean
+_get_numbers_from_usb_path (const char *path, int *usb_bus_num, int *usb_device_num, int *usb_intf_num)
+{
+ char **tokens;
+ char *endp;
+ gboolean has_brackets = FALSE;
+
+ if (path == NULL)
+ return FALSE;
+ if (*path == '[')
+ {
+ path++;
+ has_brackets = TRUE;
+ }
+
+ tokens = g_strsplit (path + 4, ",", 0);
+ if (g_strv_length (tokens) != 3)
+ {
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ *usb_bus_num = strtol (tokens[0], &endp, 10);
+ if (*endp != '\0')
+ {
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ *usb_device_num = strtol (tokens[1], &endp, 10);
+ if (*endp != '\0')
+ {
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ *usb_intf_num = strtol (tokens[2], &endp, 10);
+ if ((has_brackets && *endp != ']') || (!has_brackets && *endp != '\0'))
+ {
+ g_strfreev (tokens);
+ return FALSE;
+ }
+
+ g_strfreev (tokens);
+
+ return TRUE;
+}
+
+/* Used to detect broken listings from
+ * old Nokia 3650s */
+static gboolean
+_is_nokia_3650 (const char *bdaddr)
+{
+ if (!bdaddr)
+ return FALSE;
+
+ /* Don't ask, Nokia seem to use a Bluetooth
+ * HCI from Murata */
+ return g_str_has_prefix(bdaddr, "00:60:57");
+}
+
+static char *
+_get_bluetooth_name_and_icon (DBusGProxy *device, char **icon_name)
+{
+ GHashTable *hash;
+
+ if (dbus_g_proxy_call (device, "GetProperties", NULL,
+ G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &hash, G_TYPE_INVALID) != FALSE)
+ {
+ GValue *value;
+ char *name;
+
+ value = g_hash_table_lookup (hash, "Alias");
+ name = value ? g_value_dup_string(value) : NULL;
+
+ value = g_hash_table_lookup (hash, "Icon");
+ if (value)
+ {
+ *icon_name = g_value_dup_string (value);
+ }
+ else
+ {
+ *icon_name = g_strdup ("bluetooth");
+ }
+ g_hash_table_destroy (hash);
+ return name;
+ }
+
+ return NULL;
+}
+
+
+#define _DBUS_POINTER_SHIFT(p) ((void*) (((char*)p) + sizeof (void*)))
+#define DBUS_G_CONNECTION_FROM_CONNECTION(x) ((DBusGConnection*) _DBUS_POINTER_SHIFT(x))
+
+static gchar *
+_get_bluetooth_device_properties (const char *bdaddr, char **icon_name)
+{
+ DBusConnection *conn;
+ DBusGProxy *manager;
+ GPtrArray *adapters;
+ gchar *name;
+ guint i;
+
+ name = NULL;
+
+ conn = dbus_bus_get_private (DBUS_BUS_SYSTEM, NULL);
+ if (conn == NULL)
+ return name;
+
+ manager = dbus_g_proxy_new_for_name (DBUS_G_CONNECTION_FROM_CONNECTION(conn), "org.bluez",
+ "/", "org.bluez.Manager");
+ if (manager == NULL)
+ {
+ dbus_connection_close (conn);
+ dbus_connection_unref (conn);
+ return name;
+ }
+
+ if (dbus_g_proxy_call (manager, "ListAdapters", NULL, G_TYPE_INVALID, dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &adapters, G_TYPE_INVALID) == FALSE)
+ {
+ g_object_unref (manager);
+ dbus_connection_close (conn);
+ dbus_connection_unref (conn);
+ return name;
+ }
+
+ for (i = 0; i < adapters->len && name == NULL; i++)
+ {
+ DBusGProxy *adapter;
+ char *device_path;
+
+ adapter = dbus_g_proxy_new_for_name (DBUS_G_CONNECTION_FROM_CONNECTION(conn), "org.bluez",
+ g_ptr_array_index (adapters, i), "org.bluez.Adapter");
+ if (dbus_g_proxy_call (adapter, "FindDevice", NULL,
+ G_TYPE_STRING, bdaddr, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID) != FALSE)
+ {
+ DBusGProxy *device;
+ device = dbus_g_proxy_new_for_name (DBUS_G_CONNECTION_FROM_CONNECTION(conn), "org.bluez", device_path, "org.bluez.Device");
+ name = _get_bluetooth_name_and_icon (device, icon_name);
+ g_object_unref (device);
+ }
+ g_object_unref (adapter);
+ }
+
+ g_ptr_array_free (adapters, TRUE);
+ g_object_unref (manager);
+ dbus_connection_close (conn);
+ dbus_connection_unref (conn);
+
+ return name;
+}
+
+static gboolean
+_is_same_path (const char *path, int usb_bus_num, int usb_device_num, int usb_intf_num)
+{
+ int bus, dev, intf;
+
+ if (!_get_numbers_from_usb_path (path, &bus, &dev, &intf))
+ return FALSE;
+
+ if (bus == usb_bus_num &&
+ dev == usb_device_num &&
+ intf == usb_intf_num)
+ return TRUE;
+
+ return FALSE;
+}
+
+static int
+_find_ods_usb_intfnum (DBusGProxy *obex_manager, int device_usb_bus_num, int device_usb_device_num, int device_usb_interface_num)
+{
+ int i, n;
+ GHashTable *hash;
+
+ if (obex_manager == NULL)
+ return -1;
+
+ if (dbus_g_proxy_call (obex_manager, "GetUsbInterfacesNum", NULL, G_TYPE_INVALID, G_TYPE_UINT, &n, G_TYPE_INVALID) == FALSE)
+ return -1;
+
+ for (i = 0; i < n; i++)
+ {
+ if (dbus_g_proxy_call (obex_manager, "GetUsbInterfaceInfo", NULL,
+ G_TYPE_UINT, i, G_TYPE_INVALID,
+ DBUS_TYPE_G_STRING_STRING_HASHTABLE, &hash,
+ G_TYPE_INVALID) != FALSE)
+ {
+ const char* ods_path = g_hash_table_lookup (hash, "Path");
+
+ if (ods_path == NULL)
+ {
+ g_hash_table_destroy (hash);
+ return -2;
+ }
+
+ if (_is_same_path (ods_path, device_usb_bus_num, device_usb_device_num, device_usb_interface_num))
+ {
+ g_hash_table_destroy (hash);
+ return i;
+ }
+ g_hash_table_destroy (hash);
+ }
+ }
+ return -1;
+}
+
+static gint
+_get_usb_intfnum_and_properties (DBusGProxy *obex_manager, const char *device, char **display_name, char **icon_name)
+{
+ char **obex_devices;
+ int num_obex_devices;
+ int usb_bus_num;
+ int usb_device_num;
+ int usb_intf_num;
+ DBusError dbus_error;
+ DBusConnection *dbus_connection;
+ LibHalContext *hal_ctx;
+ int ods_intf_num = 1;
+ int n;
+
+ /* Parse the [usb:1,41,3] string */
+ if (!g_str_has_prefix (device, "[usb:"))
+ {
+ return -1;
+ }
+
+ if (!_get_numbers_from_usb_path (device, &usb_bus_num, &usb_device_num, &usb_intf_num))
+ return -1;
+
+ g_message ("Parsed '%s' into bus=%d device=%d interface=%d", device, usb_bus_num, usb_device_num, usb_intf_num);
+
+ dbus_error_init (&dbus_error);
+ dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ dbus_error_free (&dbus_error);
+ return -1;
+ }
+ dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
+
+ hal_ctx = libhal_ctx_new ();
+ if (hal_ctx == NULL)
+ {
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ dbus_error_free (&dbus_error);
+ return -1;
+ }
+
+ libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
+ if (!libhal_ctx_init (hal_ctx, &dbus_error))
+ {
+ libhal_ctx_free (hal_ctx);
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ dbus_error_free (&dbus_error);
+ return -1;
+ }
+ obex_devices = libhal_find_device_by_capability (hal_ctx, "obex", &num_obex_devices, NULL);
+
+ for (n = 0; n < num_obex_devices; n++)
+ {
+ char *udi = obex_devices[n];
+ LibHalPropertySet *ps;
+
+ ps = libhal_device_get_all_properties (hal_ctx, udi, NULL);
+ if (ps != NULL)
+ {
+ const char *subsystem;
+
+ subsystem = libhal_ps_get_string (ps, "info.subsystem");
+ if (subsystem != NULL && strcmp (subsystem, "usb") == 0)
+ {
+ int device_usb_bus_num;
+ int device_usb_device_num;
+ int device_usb_interface_num;
+ const char *icon_from_hal;
+ const char *name_from_hal;
+
+ device_usb_bus_num = libhal_ps_get_int32 (ps, "usb.bus_number");
+ device_usb_device_num = libhal_ps_get_int32 (ps, "usb.linux.device_number");
+ device_usb_interface_num = libhal_ps_get_int32 (ps, "usb.interface.number");
+ icon_from_hal = libhal_ps_get_string (ps, "info.desktop.icon");
+ name_from_hal = libhal_ps_get_string (ps, "info.desktop.name");
+
+ g_message ("looking at usb device '%s' with bus=%d, device=%d interface=%d",
+ udi, device_usb_bus_num, device_usb_device_num, device_usb_interface_num);
+
+ if (device_usb_bus_num == usb_bus_num &&
+ device_usb_device_num == usb_device_num &&
+ device_usb_interface_num == usb_intf_num)
+ {
+ const char *parent_udi;
+
+ g_message ("udi '%s' matches %s", udi, device);
+ parent_udi = libhal_ps_get_string (ps, "info.parent");
+
+ if (parent_udi != NULL)
+ {
+ LibHalPropertySet *ps2;
+
+ ps2 = libhal_device_get_all_properties (hal_ctx, parent_udi, NULL);
+ if (ps2 != NULL)
+ {
+ ods_intf_num = _find_ods_usb_intfnum (obex_manager,
+ device_usb_bus_num,
+ device_usb_device_num,
+ device_usb_interface_num);
+
+ if (ods_intf_num >= 0)
+ {
+ if (icon_from_hal != NULL)
+ *icon_name = g_strdup (icon_from_hal);
+ else
+ *icon_name = "drive-removable-media-usb";
+
+ if (name_from_hal != NULL)
+ *display_name = g_strdup (name_from_hal);
+ else
+ *display_name = g_strdup_printf ("%s - %s",
+ libhal_ps_get_string (ps2, "usb_device.vendor"),
+ libhal_ps_get_string (ps2, "usb_device.product"));
+
+ libhal_free_property_set (ps2);
+ libhal_free_property_set (ps);
+
+ goto end;
+ }
+ else if (ods_intf_num == -2)
+ {
+ libhal_free_property_set (ps2);
+ libhal_free_property_set (ps);
+
+ goto end;
+ }
+ libhal_free_property_set (ps2);
+ }
+ }
+ }
+ }
+ libhal_free_property_set (ps);
+ }
+ }
+
+end:
+ libhal_free_string_array (obex_devices);
+ libhal_ctx_free (hal_ctx);
+
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ dbus_error_free (&dbus_error);
+
+ return ods_intf_num;
+}
+
+static void
+g_vfs_backend_obexftp_finalize (GObject *object)
+{
+ GVfsBackendObexftp *backend;
+
+ backend = G_VFS_BACKEND_OBEXFTP (object);
+
+ g_free (backend->display_name);
+ g_free (backend->bdaddr);
+ g_free (backend->icon_name);
+ g_free (backend->files_listing);
+ g_free (backend->directory);
+
+ if (backend->session_proxy != NULL)
+ g_object_unref (backend->session_proxy);
+ g_mutex_free (backend->mutex);
+ g_cond_free (backend->cond);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_obexftp_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_obexftp_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_obexftp_init (GVfsBackendObexftp *backend)
+{
+ GError *err = NULL;
+
+ backend->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+ if (backend->connection == NULL) {
+ g_printerr ("Connecting to session bus failed: %s\n", err->message);
+ g_error_free (err);
+ return;
+ }
+
+ backend->mutex = g_mutex_new ();
+ backend->cond = g_cond_new ();
+ backend->manager_proxy = dbus_g_proxy_new_for_name (backend->connection,
+ "org.openobex",
+ "/org/openobex",
+ "org.openobex.Manager");
+
+ dbus_g_proxy_add_signal(backend->manager_proxy, "SessionConnectError",
+ DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(backend->manager_proxy, "SessionConnectError",
+ G_CALLBACK(session_connect_error_cb), backend, NULL);
+ dbus_g_proxy_add_signal(backend->manager_proxy, "SessionConnected",
+ DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(backend->manager_proxy, "SessionConnected",
+ G_CALLBACK(session_connected_cb), backend, NULL);
+}
+
+static gboolean
+_change_directory (GVfsBackendObexftp *op_backend,
+ const char *filename,
+ GError **error)
+{
+ char *current_path, **req_components;
+ guint i;
+
+ if (dbus_g_proxy_call (op_backend->session_proxy, "GetCurrentPath", error,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &current_path, G_TYPE_INVALID) == FALSE)
+ {
+ g_message ("GetCurrentPath failed");
+ return FALSE;
+ }
+
+ if (strcmp (filename, current_path) == 0)
+ {
+ g_free (current_path);
+ return TRUE;
+ }
+
+ /* Are we already at the root? */
+ if (strcmp (current_path, "/") != 0)
+ {
+ if (dbus_g_proxy_call (op_backend->session_proxy, "ChangeCurrentFolderToRoot", error,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_message ("ChangeCurrentFolderToRoot failed");
+ //FIXME change the retval from org.openobex.Error.NotAuthorized to
+ //no such file or directory
+ return FALSE;
+ }
+ }
+ g_free (current_path);
+
+ /* If we asked for the root, we're done */
+ if (strcmp (filename, "/") == 0)
+ return TRUE;
+
+ req_components = g_strsplit (filename, "/", -1);
+ for (i = 0; req_components[i] != NULL; i++)
+ {
+ if (*req_components[i] == '\0')
+ continue;
+ if (dbus_g_proxy_call (op_backend->session_proxy, "ChangeCurrentFolder", error,
+ G_TYPE_STRING, req_components[i], G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_message ("ChangeCurrentFolder failed");
+ g_strfreev (req_components);
+ return FALSE;
+ }
+ }
+
+ g_strfreev (req_components);
+
+ return TRUE;
+}
+
+static gboolean
+_retrieve_folder_listing (GVfsBackend *backend,
+ const char *filename,
+ char **files,
+ GError **error)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ time_t current;
+
+ current = time (NULL);
+
+ if (op_backend->directory != NULL &&
+ strcmp (op_backend->directory, filename) == 0 &&
+ op_backend->time_captured > current - CACHE_LIFESPAN)
+ {
+ *files = g_strdup (op_backend->files_listing);
+ return TRUE;
+ }
+ else
+ {
+ g_free (op_backend->directory);
+ op_backend->directory = NULL;
+ g_free (op_backend->files_listing);
+ op_backend->files_listing = NULL;
+ }
+
+ if (dbus_g_proxy_call (op_backend->session_proxy, "RetrieveFolderListing", error,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, files, G_TYPE_INVALID) == FALSE)
+ {
+ return FALSE;
+ }
+
+ op_backend->directory = g_strdup (filename);
+ op_backend->files_listing = g_strdup (*files);
+ op_backend->time_captured = time (NULL);
+
+ return TRUE;
+}
+
+static gboolean
+_query_file_info_helper (GVfsBackend *backend,
+ const char *filename,
+ GFileInfo *info,
+ GError **error)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ char *parent, *basename, *files;
+ GList *elements, *l;
+ gboolean found;
+
+ g_debug ("+ _query_file_info_helper, filename: %s\n", filename);
+
+ if (strcmp (filename, "/") == 0)
+ {
+ char *display;
+
+ /* That happens when you want '/'
+ * and we don't have any info about it :( */
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
+ g_file_info_set_name (info, "/");
+ if (op_backend->icon_name) {
+ GIcon *icon;
+
+ g_vfs_backend_set_icon_name (backend, op_backend->icon_name);
+ icon = g_themed_icon_new (op_backend->icon_name);
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+ display = g_strdup_printf (_("%s on %s"), "/", op_backend->display_name);
+ g_file_info_set_display_name (info, display);
+ g_free (display);
+ return TRUE;
+ }
+
+ parent = g_path_get_dirname (filename);
+ if (_change_directory (op_backend, parent, error) == FALSE)
+ {
+ g_free (parent);
+ return FALSE;
+ }
+
+ files = NULL;
+ if (_retrieve_folder_listing (backend, parent, &files, error) == FALSE)
+ {
+ g_free (parent);
+ return FALSE;
+ }
+
+ g_free (parent);
+
+ if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, error) == FALSE)
+ {
+ g_free (files);
+ return FALSE;
+ }
+ g_free (files);
+
+ basename = g_path_get_basename (filename);
+ found = FALSE;
+
+ for (l = elements; l != NULL; l = l->next)
+ {
+ if (strcmp (basename, g_file_info_get_name (l->data)) == 0)
+ {
+ g_file_info_copy_into (l->data, info);
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found == FALSE)
+ {
+ g_set_error_literal (error, G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ g_strerror (ENOENT));
+ }
+
+ g_free (basename);
+ g_list_foreach (elements, (GFunc)g_object_unref, NULL);
+ g_list_free (elements);
+
+ g_debug ("- _query_file_info_helper\n");
+
+ return found;
+}
+
+static void
+_invalidate_cache_helper (GVfsBackendObexftp *op_backend)
+{
+ g_free (op_backend->directory);
+ op_backend->directory = NULL;
+}
+
+static void
+error_occurred_cb (DBusGProxy *proxy, const gchar *error_name, const gchar *error_message, gpointer user_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data);
+
+ g_message("ErrorOccurred");
+ g_message("Error name: %s", error_name);
+ g_message("Error message: %s", error_message);
+
+ if (strcmp (error_name, "org.openobex.Error.LinkError") == 0)
+ {
+ g_message ("link lost to remote device");
+ _exit (1);
+ }
+
+ /* Something is waiting on us */
+ g_mutex_lock (op_backend->mutex);
+ if (op_backend->doing_io)
+ {
+ op_backend->status = ASYNC_ERROR;
+ op_backend->error = g_error_new_literal (DBUS_GERROR,
+ DBUS_GERROR_REMOTE_EXCEPTION,
+ error_message);
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+ return;
+ }
+ g_mutex_unlock (op_backend->mutex);
+
+ g_message ("Unhandled error, file a bug");
+ _exit (1);
+}
+
+static void
+session_connect_error_cb (DBusGProxy *proxy,
+ const char *session_object,
+ const gchar *error_name,
+ const gchar *error_message,
+ gpointer user_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data);
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->status = ASYNC_ERROR;
+ op_backend->error = g_error_new_literal (DBUS_GERROR,
+ DBUS_GERROR_REMOTE_EXCEPTION,
+ error_message);
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+session_connected_cb (DBusGProxy *proxy,
+ const char *session_object,
+ gpointer user_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data);
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->status = ASYNC_SUCCESS;
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+cancelled_cb (DBusGProxy *proxy, gpointer user_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data);
+
+ g_message ("transfer got cancelled");
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->status = ASYNC_ERROR;
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+disconnected_cb (DBusGProxy *proxy, gpointer user_data)
+{
+ g_message ("disconnected_cb");
+
+ _exit (1);
+}
+
+static void
+closed_cb (DBusGProxy *proxy, gpointer user_data)
+{
+ g_message ("closed_cb");
+
+ _exit (1);
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ const char *device;
+ GError *error = NULL;
+ const gchar *path = NULL;
+ GMountSpec *obexftp_mount_spec;
+ guint count;
+
+ g_debug ("+ do_mount\n");
+
+ device = g_mount_spec_get (mount_spec, "host");
+
+ if (device == NULL || (strlen (device) != BDADDR_LEN + 2 && !g_str_has_prefix(device, "[usb:")) )
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+
+ op_backend->bdaddr = NULL;
+ op_backend->usbintfnum = -1;
+
+ if (!g_str_has_prefix(device, "[usb:"))
+ {
+ /* Strip the brackets */
+ op_backend->bdaddr = g_strndup (device + 1, BDADDR_LEN);
+ if (bachk (op_backend->bdaddr) < 0)
+ {
+ g_free (op_backend->bdaddr);
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+ }
+ else
+ {
+ op_backend->usbintfnum = _get_usb_intfnum_and_properties (op_backend->manager_proxy, device, &op_backend->display_name, &op_backend->icon_name);
+ if (op_backend->usbintfnum < 0)
+ {
+ if (op_backend->usbintfnum == -2)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("USB support missing. Please contact your software vendor"));
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ }
+ return;
+ }
+ }
+
+ /* FIXME, Have a way for the mount to be cancelled, see:
+ * Use CancelSessionConnect */
+ op_backend->status = ASYNC_PENDING;
+
+ if (op_backend->bdaddr)
+ {
+ if (dbus_g_proxy_call (op_backend->manager_proxy, "CreateBluetoothSession", &error,
+ G_TYPE_STRING, op_backend->bdaddr, G_TYPE_STRING, "00:00:00:00:00:00", G_TYPE_STRING, "ftp", G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID) == FALSE)
+ {
+ g_free (op_backend->bdaddr);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ op_backend->display_name = _get_bluetooth_device_properties (op_backend->bdaddr, &op_backend->icon_name);
+ if (!op_backend->display_name)
+ op_backend->display_name = g_strdelimit (g_strdup (op_backend->bdaddr), ":", '-');
+ if (!op_backend->icon_name)
+ op_backend->icon_name = g_strdup ("bluetooth");
+ g_debug (" do_mount: %s (%s) mounted\n", op_backend->display_name, op_backend->bdaddr);
+ }
+ else
+ {
+ if (dbus_g_proxy_call (op_backend->manager_proxy, "CreateUsbSession", &error,
+ G_TYPE_UINT, op_backend->usbintfnum, G_TYPE_STRING, "ftp", G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID) == FALSE)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_debug (" do_mount: usb interface %d mounted\n", op_backend->usbintfnum);
+ }
+
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), backend, NULL);
+
+ op_backend->session_proxy = dbus_g_proxy_new_for_name (op_backend->connection,
+ "org.openobex",
+ path,
+ "org.openobex.Session");
+
+ g_vfs_backend_set_display_name (G_VFS_BACKEND (op_backend),
+ op_backend->display_name);
+ g_vfs_backend_set_icon_name (G_VFS_BACKEND (op_backend), op_backend->icon_name);
+
+ obexftp_mount_spec = g_mount_spec_new ("obex");
+ g_mount_spec_set (obexftp_mount_spec, "host", device);
+ g_vfs_backend_set_mount_spec (G_VFS_BACKEND (op_backend), obexftp_mount_spec);
+ g_mount_spec_unref (obexftp_mount_spec);
+
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "ErrorOccurred",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(op_backend->session_proxy, "ErrorOccurred",
+ G_CALLBACK(error_occurred_cb), op_backend, NULL);
+
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "Cancelled",
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(op_backend->session_proxy, "Cancelled",
+ G_CALLBACK(cancelled_cb), op_backend, NULL);
+
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "Disconnected",
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(op_backend->session_proxy, "Disconnected",
+ G_CALLBACK(disconnected_cb), op_backend, NULL);
+
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "Closed",
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(op_backend->session_proxy, "Closed",
+ G_CALLBACK(closed_cb), op_backend, NULL);
+
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "TransferStarted",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "TransferCompleted",
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(op_backend->session_proxy, "TransferProgress",
+ G_TYPE_UINT64, G_TYPE_INVALID);
+
+ /* Now wait until the device is connected */
+ count = 0;
+ g_mutex_lock (op_backend->mutex);
+
+ while (op_backend->status == ASYNC_PENDING && count < 100) {
+ GTimeVal val;
+ g_get_current_time (&val);
+ g_time_val_add (&val, 100000);
+ count++;
+ if (g_cond_timed_wait (op_backend->cond, op_backend->mutex, &val) != FALSE)
+ break;
+ }
+ g_mutex_unlock (op_backend->mutex);
+
+ if (op_backend->status == ASYNC_ERROR || op_backend->status == ASYNC_PENDING)
+ {
+ g_message ("mount failed, didn't connect");
+
+ g_free (op_backend->display_name);
+ op_backend->display_name = NULL;
+ g_free (op_backend->bdaddr);
+ op_backend->bdaddr = NULL;
+ g_object_unref (op_backend->session_proxy);
+ op_backend->session_proxy = NULL;
+
+ if (op_backend->status != ASYNC_PENDING)
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), op_backend->error);
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("Connection to the device lost"));
+ return;
+ }
+
+ op_backend->status = ASYNC_PENDING;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_debug ("- do_mount\n");
+}
+
+static void
+transfer_started_cb (DBusGProxy *proxy, const gchar *filename,
+ const gchar *local_path, guint64 byte_count, gpointer user_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data);
+
+ g_message ("transfer of %s to %s started", filename, local_path);
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->status = ASYNC_SUCCESS;
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ GError *error = NULL;
+ ObexFTPOpenHandle *handle;
+ char *target, *basename;
+ GFileInfo *info;
+ goffset size;
+ int fd, success;
+
+ g_debug ("+ do_open_for_read, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->doing_io = TRUE;
+
+ /* Change into the directory and cache the file size */
+ info = g_file_info_new ();
+ if (_query_file_info_helper (backend, filename, info, &error) == FALSE)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_object_unref (info);
+ return;
+ }
+ /* If we're trying to open a directory for reading, exit out */
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+ g_object_unref (info);
+ return;
+ }
+
+ size = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ fd = g_file_open_tmp ("gvfsobexftp-tmp-XXXXXX",
+ &target, &error);
+ if (fd < 0)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ op_backend->status = ASYNC_PENDING;
+
+ dbus_g_proxy_connect_signal(op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK(transfer_started_cb), op_backend, NULL);
+
+ basename = g_path_get_basename (filename);
+ if (dbus_g_proxy_call (op_backend->session_proxy, "CopyRemoteFile", &error,
+ G_TYPE_STRING, basename,
+ G_TYPE_STRING, target,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_message ("CopyRemoteFile failed");
+
+ g_free (basename);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ dbus_g_proxy_disconnect_signal(op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK(transfer_started_cb), op_backend);
+
+ /* Close the target */
+ g_unlink (target);
+ g_free (target);
+ close (fd);
+
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ return;
+ }
+
+ /* Wait for TransferStarted or ErrorOccurred to have happened */
+ while (op_backend->status == ASYNC_PENDING)
+ g_cond_wait (op_backend->cond, op_backend->mutex);
+ success = op_backend->status;
+ dbus_g_proxy_disconnect_signal(op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK(transfer_started_cb), op_backend);
+
+ /* We either got success or an async error */
+ g_assert (success != ASYNC_PENDING);
+
+ g_message ("filename: %s (%s) copying to %s (retval %d)", filename, basename, target, success);
+ g_free (basename);
+
+ g_unlink (target);
+ g_free (target);
+ op_backend->status = ASYNC_PENDING;
+
+ if (success == ASYNC_ERROR)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ close (fd);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job),
+ op_backend->error);
+ g_error_free (op_backend->error);
+ op_backend->error = NULL;
+ return;
+ }
+
+ handle = g_new0 (ObexFTPOpenHandle, 1);
+ handle->source = g_strdup (filename);
+ handle->fd = fd;
+ handle->size = size;
+ g_vfs_job_open_for_read_set_handle (job, handle);
+
+ g_debug ("- do_open_for_read, filename: %s\n", filename);
+
+ g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), FALSE);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static int
+is_busy (DBusGProxy *session_proxy, GVfsJob *job)
+{
+ GError *error = NULL;
+ gboolean busy;
+
+ if (dbus_g_proxy_call (session_proxy, "IsBusy", &error,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &busy, G_TYPE_INVALID) == FALSE)
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ return -1;
+ }
+
+ return busy;
+}
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ ObexFTPOpenHandle *backend_handle = (ObexFTPOpenHandle *) handle;
+ ssize_t bytes_read = 0;
+ gboolean busy = TRUE;
+
+ while (bytes_read == 0 && busy != FALSE)
+ {
+ bytes_read = read (backend_handle->fd, buffer, bytes_requested);
+ if (bytes_read != 0)
+ break;
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ busy = is_busy (op_backend->session_proxy, G_VFS_JOB (job));
+ if (busy < 0)
+ return;
+
+ g_usleep (G_USEC_PER_SEC / 100);
+ }
+
+ if (bytes_read < 0)
+ {
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ }
+ else if (bytes_read == 0)
+ {
+ g_vfs_job_read_set_size (job, 0);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_read_set_size (job, bytes_read);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ ObexFTPOpenHandle *backend_handle = (ObexFTPOpenHandle *) handle;
+ int busy;
+
+ g_debug ("+ do_close_read\n");
+
+ busy = is_busy (op_backend->session_proxy, G_VFS_JOB (job));
+ if (busy < 0) {
+ g_message ("busy error");
+ return;
+ }
+
+ g_mutex_lock (op_backend->mutex);
+
+ if (busy > 0)
+ {
+ op_backend->status = ASYNC_PENDING;
+
+ if (dbus_g_proxy_call (op_backend->session_proxy, "Cancel", NULL,
+ G_TYPE_INVALID, G_TYPE_INVALID) != FALSE)
+ {
+ while (op_backend->status == ASYNC_PENDING)
+ g_cond_wait (op_backend->cond, op_backend->mutex);
+ }
+ }
+
+ g_mutex_unlock (op_backend->mutex);
+
+ close (backend_handle->fd);
+ g_free (backend_handle->source);
+ g_free (backend_handle);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_debug ("- do_close_read\n");
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ GError *error = NULL;
+
+ g_debug ("+ do_query_info, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+
+ if (_query_file_info_helper (backend, filename, info, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ g_mutex_unlock (op_backend->mutex);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_debug ("- do_query_info\n");
+
+ return;
+}
+
+static void
+do_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ OvuCaps *caps;
+ OvuCapsMemory *memory;
+ GError *error = NULL;
+ char *caps_str;
+ const char *mem_type;
+ GList *l;
+ gboolean has_free_memory;
+
+ g_debug ("+ do_query_fs_info, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+
+ /* Get the capabilities */
+ if (dbus_g_proxy_call (op_backend->session_proxy, "GetCapability", &error,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &caps_str, G_TYPE_INVALID) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_free (caps_str);
+ return;
+ }
+
+ /* No caps from the server? */
+ if (caps_str == NULL)
+ {
+ /* Best effort, don't error out */
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return;
+ }
+
+ caps = ovu_caps_parser_parse (caps_str, strlen (caps_str), &error);
+ g_free (caps_str);
+ if (caps == NULL)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ /* Check whether we have no free space available */
+ has_free_memory = FALSE;
+ for (l = ovu_caps_get_memory_entries (caps); l != NULL; l = l->next)
+ {
+ if (ovu_caps_memory_has_free (l->data) != FALSE)
+ {
+ has_free_memory = TRUE;
+ break;
+ }
+ }
+ if (has_free_memory == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ /* Best effort, don't error out */
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return;
+ }
+
+ /* Check whether we have only one memory type */
+ l = ovu_caps_get_memory_entries (caps);
+ if (g_list_length (l) == 1)
+ {
+ memory = l->data;
+ goto set_info_from_memory;
+ }
+
+ if (_query_file_info_helper (backend, filename, info, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ ovu_caps_free (caps);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ ovu_caps_free (caps);
+ return;
+ }
+
+ mem_type = NULL;
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_RDEV) != FALSE)
+ {
+ guint rdev;
+ rdev = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV);
+ mem_type = om_mem_type_id_to_string (rdev);
+ }
+ memory = ovu_caps_get_memory_type (caps, mem_type);
+
+set_info_from_memory:
+ if (memory != NULL && ovu_caps_memory_has_free (memory) != FALSE)
+ {
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
+ ovu_caps_memory_get_free (memory));
+ if (ovu_caps_memory_has_used (memory) != FALSE)
+ {
+ g_file_info_set_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,
+ ovu_caps_memory_get_free (memory)
+ + ovu_caps_memory_get_used (memory));
+ }
+ }
+ ovu_caps_free (caps);
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "obexftp");
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_mutex_unlock (op_backend->mutex);
+
+ g_debug ("- do_query_fs_info\n");
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ GError *error = NULL;
+ char *files;
+ GList *elements = NULL;
+
+ g_debug ("+ do_enumerate, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+
+ if (_change_directory (op_backend, filename, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ files = NULL;
+ if (_retrieve_folder_listing (backend, filename, &files, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ /* See http://web.archive.org/web/20070826221251/http://docs.kde.org/development/en/extragear-pim/kdebluetooth/components.kio_obex.html#devices
+ * for the reasoning */
+ if (strstr (files, "SYSTEM\"obex-folder-listing.dtd") != NULL && _is_nokia_3650 (op_backend->bdaddr))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Device requires a software update"));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ }
+ g_message ("gvfsbackendobexftp_fl_parser_parse failed");
+ g_free (files);
+ g_error_free (error);
+ return;
+ }
+ g_free (files);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_vfs_job_enumerate_add_infos (job, elements);
+
+ g_list_foreach (elements, (GFunc)g_object_unref, NULL);
+ g_list_free (elements);
+ g_vfs_job_enumerate_done (job);
+
+ g_mutex_unlock (op_backend->mutex);
+
+ g_debug ("- do_enumerate\n");
+}
+
+typedef struct {
+ GVfsBackendObexftp *op_backend;
+ GFileProgressCallback progress_callback;
+ gpointer progress_callback_data;
+ goffset total_bytes;
+} PushData;
+
+static void
+push_transfer_started_cb (DBusGProxy *proxy,
+ const gchar *filename,
+ const gchar *local_path,
+ guint64 total_bytes,
+ gpointer user_data)
+{
+ PushData *job_data = (PushData *) user_data;
+ GVfsBackendObexftp *op_backend = job_data->op_backend;
+
+ g_message ("transfer of %s to %s started", filename, local_path);
+
+ g_mutex_lock (op_backend->mutex);
+
+ op_backend->status = ASYNC_RUNNING;
+ job_data->total_bytes = (goffset) total_bytes;
+ job_data->progress_callback (0, job_data->total_bytes,
+ job_data->progress_callback_data);
+
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+push_transfer_completed_cb (DBusGProxy *proxy,
+ gpointer user_data)
+{
+ PushData *job_data = (PushData *) user_data;
+ GVfsBackendObexftp *op_backend = job_data->op_backend;
+
+ g_message ("transfer completed");
+
+ g_mutex_lock (op_backend->mutex);
+
+ op_backend->status = ASYNC_SUCCESS;
+
+ g_cond_signal (op_backend->cond);
+ g_mutex_unlock (op_backend->mutex);
+}
+
+static void
+push_transfer_progress_cb (DBusGProxy *proxy,
+ guint64 bytes_transferred,
+ gpointer user_data)
+{
+ PushData *job_data = (PushData *) user_data;
+
+ g_message ("transfer progress");
+
+ job_data->progress_callback ((goffset) bytes_transferred,
+ job_data->total_bytes,
+ job_data->progress_callback_data);
+}
+
+static void
+push_data_free (PushData *job_data)
+{
+ g_object_unref (job_data->op_backend);
+ g_slice_free (PushData, job_data);
+}
+
+static gboolean
+_push_single_file_helper (GVfsBackendObexftp *op_backend,
+ GVfsJobPush *job,
+ const char *local_path,
+ const char *destination,
+ GError **error,
+ PushData *job_data)
+{
+ char *dirname;
+ int success;
+
+ dirname = g_path_get_dirname (destination);
+
+ if (_change_directory (op_backend, dirname, error) == FALSE)
+ {
+ g_free (dirname);
+ return FALSE;
+ }
+
+ g_free (dirname);
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_set_error_literal (error, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return FALSE;
+ }
+
+ op_backend->status = ASYNC_PENDING;
+
+ /* connect to the transfer signals */
+ dbus_g_proxy_connect_signal (op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK (push_transfer_started_cb), job_data,
+ NULL);
+ dbus_g_proxy_connect_signal (op_backend->session_proxy, "TransferCompleted",
+ G_CALLBACK (push_transfer_completed_cb), job_data,
+ NULL);
+ dbus_g_proxy_connect_signal (op_backend->session_proxy, "TransferProgress",
+ G_CALLBACK (push_transfer_progress_cb), job_data,
+ NULL);
+
+ if (dbus_g_proxy_call (op_backend->session_proxy, "SendFile", error,
+ G_TYPE_STRING, local_path, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK (push_transfer_started_cb), job_data);
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferCompleted",
+ G_CALLBACK (push_transfer_completed_cb), job_data);
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferProgress",
+ G_CALLBACK (push_transfer_progress_cb), job_data);
+ return FALSE;
+ }
+
+ /* wait for the TransferStarted or ErrorOccurred signal */
+ while (op_backend->status == ASYNC_PENDING)
+ g_cond_wait (op_backend->cond, op_backend->mutex);
+
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferStarted",
+ G_CALLBACK (push_transfer_started_cb), job_data);
+ success = op_backend->status;
+
+ /* we either got the operation running or an error */
+ if (success == ASYNC_ERROR)
+ {
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferCompleted",
+ G_CALLBACK (push_transfer_completed_cb), job_data);
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferProgress",
+ G_CALLBACK (push_transfer_progress_cb), job_data);
+
+ *error = g_error_copy (op_backend->error);
+ g_error_free (op_backend->error);
+ op_backend->error = NULL;
+ return FALSE;
+ }
+
+ while (op_backend->status == ASYNC_RUNNING)
+ g_cond_wait (op_backend->cond, op_backend->mutex);
+
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferCompleted",
+ G_CALLBACK (push_transfer_completed_cb), job_data);
+ dbus_g_proxy_disconnect_signal (op_backend->session_proxy, "TransferProgress",
+ G_CALLBACK (push_transfer_progress_cb), job_data);
+ success = op_backend->status;
+
+ /* same as before, either we have success or an error */
+ if (success == ASYNC_ERROR)
+ {
+ *error = g_error_copy (op_backend->error);
+ g_error_free (op_backend->error);
+ op_backend->error = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+do_push (GVfsBackend *backend,
+ GVfsJobPush *job,
+ const char *destination,
+ const char *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ GError *error = NULL;
+ gboolean is_dir, overwrite, res;
+ GFileType target_type;
+ PushData *job_data;
+ GFileInfo *info;
+
+ g_debug ("+ do_push, destination: %s, local_path: %s\n", destination, local_path);
+
+ g_mutex_lock (op_backend->mutex);
+ op_backend->doing_io = TRUE;
+
+ overwrite = (flags & G_FILE_COPY_OVERWRITE);
+ is_dir = g_file_test (local_path, G_FILE_TEST_IS_DIR);
+ info = g_file_info_new ();
+ target_type = 0;
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ res = _query_file_info_helper (backend, destination, info, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return;
+ }
+ else
+ {
+ g_clear_error (&error);
+ res = TRUE;
+ }
+ }
+
+ if (res)
+ target_type = g_file_info_get_file_type (info);
+
+ g_object_unref (info);
+
+ /* error handling */
+ if (is_dir)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+
+ if (target_type != 0)
+ {
+ if (overwrite)
+ {
+ if (target_type == G_FILE_TYPE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_WOULD_MERGE,
+ _("Can't copy directory over directory"));
+ return;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file exists"));
+ return;
+ }
+ }
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_WOULD_RECURSE,
+ _("Can't recursively copy directory"));
+ return;
+ }
+ else
+ {
+ if (target_type != 0)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+
+ if (overwrite)
+ {
+ if (target_type == G_FILE_TYPE_DIRECTORY)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("Can't copy file over directory"));
+ return;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file exists"));
+ return;
+ }
+ }
+ }
+
+ job_data = g_slice_new0 (PushData);
+ job_data->op_backend = g_object_ref (op_backend);
+ job_data->progress_callback = progress_callback;
+ job_data->progress_callback_data = progress_callback_data;
+
+ /* start the actual transfer operation */
+ if (_push_single_file_helper (op_backend, job, local_path, destination,
+ &error, job_data) == FALSE)
+ {
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+ push_data_free (job_data);
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ }
+
+ push_data_free (job_data);
+
+ /* we called _query_file_info_helper (), so we need to invalidate the
+ * cache, as a query_info () will be called on us after we return.
+ */
+ _invalidate_cache_helper (op_backend);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ op_backend->doing_io = FALSE;
+ g_mutex_unlock (op_backend->mutex);
+
+ g_debug ("- do_push\n");
+}
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ char *basename, *parent;
+ GError *error = NULL;
+ GFileInfo *info;
+
+ g_debug ("+ do_delete, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+
+ /* Check whether we have a directory */
+ info = g_file_info_new ();
+ if (_query_file_info_helper (backend, filename, info, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_object_unref (info);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_object_unref (info);
+ return;
+ }
+
+ /* Get the listing of the directory, and abort if it's not empty */
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ {
+ GList *elements;
+ char *files;
+ guint len;
+
+ g_object_unref (info);
+
+ if (_change_directory (op_backend, filename, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ files = NULL;
+ if (_retrieve_folder_listing (backend, filename, &files, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_message ("gvfsbackendobexftp_fl_parser_parse failed");
+ g_free (files);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_free (files);
+
+ len = g_list_length (elements);
+ g_list_foreach (elements, (GFunc)g_object_unref, NULL);
+ g_list_free (elements);
+
+ if (len != 0)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_set_error_literal (&error, G_IO_ERROR,
+ G_IO_ERROR_NOT_EMPTY,
+ g_strerror (ENOTEMPTY));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ }
+ else
+ {
+ g_object_unref (info);
+ }
+
+ basename = g_path_get_basename (filename);
+ if (strcmp (basename, G_DIR_SEPARATOR_S) == 0
+ || strcmp (basename, ".") == 0)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_free (basename);
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), EPERM);
+ return;
+ }
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_free (basename);
+ return;
+ }
+
+ parent = g_path_get_dirname (filename);
+ if (_change_directory (op_backend, parent, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_free (basename);
+ g_free (parent);
+ g_error_free (error);
+ return;
+ }
+ g_free (parent);
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_free (basename);
+ return;
+ }
+
+ if (dbus_g_proxy_call (op_backend->session_proxy, "DeleteRemoteFile", &error,
+ G_TYPE_STRING, basename, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_free (basename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_mutex_unlock (op_backend->mutex);
+
+ g_debug ("- do_delete\n");
+}
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend);
+ char *basename, *parent;
+ GError *error = NULL;
+ GFileInfo *info;
+
+ g_debug ("+ do_make_directory, filename: %s\n", filename);
+
+ g_mutex_lock (op_backend->mutex);
+
+ /* Check if the folder already exists */
+ info = g_file_info_new ();
+ if (_query_file_info_helper (backend, filename, info, &error) != FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_object_unref (info);
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), EEXIST);
+ return;
+ }
+ g_object_unref (info);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (error)
+ g_clear_error (&error);
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ parent = g_path_get_dirname (filename);
+ if (_change_directory (op_backend, parent, &error) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_free (parent);
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return;
+ }
+
+ basename = g_path_get_basename (filename);
+ if (dbus_g_proxy_call (op_backend->session_proxy, "CreateFolder", &error,
+ G_TYPE_STRING, basename, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_mutex_unlock (op_backend->mutex);
+ g_free (basename);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_free (basename);
+
+ /* reset the current directory so that we won't cache when querying
+ * info after this has succeeded.
+ */
+ _invalidate_cache_helper (op_backend);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_mutex_unlock (op_backend->mutex);
+
+ g_debug ("- do_make_directory\n");
+}
+
+static void
+g_vfs_backend_obexftp_class_init (GVfsBackendObexftpClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_obexftp_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->read = do_read;
+ backend_class->close_read = do_close_read;
+ backend_class->query_info = do_query_info;
+ backend_class->query_fs_info = do_query_fs_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->delete = do_delete;
+ backend_class->make_directory = do_make_directory;
+ backend_class->push = do_push;
+
+ /* ErrorOccurred */
+ dbus_g_object_register_marshaller (obexftp_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_INVALID);
+ /* TransferStarted */
+ dbus_g_object_register_marshaller(obexftp_marshal_VOID__STRING_STRING_UINT64,
+ G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+ /* TransferProgress */
+ dbus_g_object_register_marshaller(obexftp_marshal_VOID__UINT64,
+ G_TYPE_NONE, G_TYPE_UINT64, G_TYPE_INVALID);
+ /* SessionConnected */
+ dbus_g_object_register_marshaller(obexftp_marshal_VOID__STRING,
+ G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+ /* SessionConnectError */
+ dbus_g_object_register_marshaller (obexftp_marshal_VOID__STRING_STRING_STRING,
+ G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+}
+
+/*
+ * vim: sw=2 ts=8 cindent expandtab cinoptions=f0,>4,n2,{2,(0,^-2,t0 ai
+ */
diff --git a/trunk/daemon/gvfsbackendobexftp.h b/trunk/daemon/gvfsbackendobexftp.h
new file mode 100644
index 00000000..434749bb
--- /dev/null
+++ b/trunk/daemon/gvfsbackendobexftp.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_OBEXFTP_H__
+#define __G_VFS_BACKEND_OBEXFTP_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_OBEXFTP (g_vfs_backend_obexftp_get_type ())
+#define G_VFS_BACKEND_OBEXFTP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_OBEXFTP, GVfsBackendObexftp))
+#define G_VFS_BACKEND_OBEXFTP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_OBEXFTP, GVfsBackendObexftpClass))
+#define G_VFS_IS_BACKEND_OBEXFTP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_OBEXFTP))
+#define G_VFS_IS_BACKEND_OBEXFTP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_OBEXFTP))
+#define G_VFS_BACKEND_OBEXFTP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_OBEXFTP, GVfsBackendObexftpClass))
+
+typedef struct _GVfsBackendObexftp GVfsBackendObexftp;
+typedef struct _GVfsBackendObexftpClass GVfsBackendObexftpClass;
+
+struct _GVfsBackendObexftpClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_obexftp_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_OBEXFTP_H__ */
diff --git a/trunk/daemon/gvfsbackendsftp.c b/trunk/daemon/gvfsbackendsftp.c
new file mode 100644
index 00000000..c115b849
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsftp.c
@@ -0,0 +1,4202 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+
+#include "gvfsicon.h"
+
+#include "gvfsbackendsftp.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobopeniconforread.h"
+#include "gvfsjobmount.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryinforead.h"
+#include "gvfsjobqueryinfowrite.h"
+#include "gvfsjobmove.h"
+#include "gvfsjobdelete.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfskeyring.h"
+#include "sftp.h"
+#include "pty_open.h"
+
+/* TODO for sftp:
+ * Implement can_delete & can_rename
+ * fstat
+ */
+
+#ifdef HAVE_GRANTPT
+/* We only use this on systems with unix98 ptys */
+#define USE_PTY 1
+#endif
+
+static GQuark id_q;
+
+typedef enum {
+ SFTP_VENDOR_INVALID = 0,
+ SFTP_VENDOR_OPENSSH,
+ SFTP_VENDOR_SSH
+} SFTPClientVendor;
+
+typedef struct _MultiReply MultiReply;
+
+typedef void (*ReplyCallback) (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data);
+
+typedef void (*MultiReplyCallback) (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data);
+
+
+typedef struct {
+ MultiReply *replies;
+ int n_replies;
+ int n_outstanding;
+ gpointer user_data;
+ MultiReplyCallback callback;
+} MultiRequest;
+
+struct _MultiReply {
+ int type;
+ GDataInputStream *data;
+ guint32 data_len;
+
+ MultiRequest *request;
+};
+
+
+
+typedef struct {
+ guchar *data;
+ gsize size;
+} DataBuffer;
+
+typedef struct {
+ DataBuffer *raw_handle;
+ goffset offset;
+ char *filename;
+ char *tempname;
+ guint32 permissions;
+ gboolean make_backup;
+} SftpHandle;
+
+
+typedef struct {
+ ReplyCallback callback;
+ GVfsJob *job;
+ gpointer user_data;
+} ExpectedReply;
+
+struct _GVfsBackendSftp
+{
+ GVfsBackend parent_instance;
+
+ SFTPClientVendor client_vendor;
+ char *host;
+ int port;
+ gboolean user_specified;
+ char *user;
+ char *tmp_password;
+
+ guint32 my_uid;
+ guint32 my_gid;
+
+ int protocol_version;
+
+ GOutputStream *command_stream;
+ GInputStream *reply_stream;
+ GDataInputStream *error_stream;
+
+ guint32 current_id;
+
+ /* Output Queue */
+
+ gsize command_bytes_written;
+ GList *command_queue;
+
+ /* Reply reading: */
+ GHashTable *expected_replies;
+ guint32 reply_size;
+ guint32 reply_size_read;
+ guint8 *reply;
+
+ GMountSource *mount_source; /* Only used/set during mount */
+ int mount_try;
+ gboolean mount_try_again;
+};
+
+static void parse_attributes (GVfsBackendSftp *backend,
+ GFileInfo *info,
+ const char *basename,
+ GDataInputStream *reply,
+ GFileAttributeMatcher *attribute_matcher);
+
+static void setup_icon (GVfsBackendSftp *op_backend,
+ GVfsJobMount *job);
+
+
+G_DEFINE_TYPE (GVfsBackendSftp, g_vfs_backend_sftp, G_VFS_TYPE_BACKEND)
+
+static void
+data_buffer_free (DataBuffer *buffer)
+{
+ if (buffer)
+ {
+ g_free (buffer->data);
+ g_slice_free (DataBuffer, buffer);
+ }
+}
+
+static void
+make_fd_nonblocking (int fd)
+{
+ fcntl (fd, F_SETFL, O_NONBLOCK | fcntl (fd, F_GETFL));
+}
+
+static SFTPClientVendor
+get_sftp_client_vendor (void)
+{
+ char *ssh_stderr;
+ char *args[3];
+ gint ssh_exitcode;
+ SFTPClientVendor res = SFTP_VENDOR_INVALID;
+
+ args[0] = g_strdup (SSH_PROGRAM);
+ args[1] = g_strdup ("-V");
+ args[2] = NULL;
+ if (g_spawn_sync (NULL, args, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL,
+ NULL, NULL,
+ NULL, &ssh_stderr,
+ &ssh_exitcode, NULL))
+ {
+ if (ssh_stderr == NULL)
+ res = SFTP_VENDOR_INVALID;
+ else if ((strstr (ssh_stderr, "OpenSSH") != NULL) ||
+ (strstr (ssh_stderr, "Sun_SSH") != NULL))
+ res = SFTP_VENDOR_OPENSSH;
+ else if (strstr (ssh_stderr, "SSH Secure Shell") != NULL)
+ res = SFTP_VENDOR_SSH;
+ else
+ res = SFTP_VENDOR_INVALID;
+ }
+
+ g_free (ssh_stderr);
+ g_free (args[0]);
+ g_free (args[1]);
+
+ return res;
+}
+
+static void
+g_vfs_backend_sftp_finalize (GObject *object)
+{
+ GVfsBackendSftp *backend;
+
+ backend = G_VFS_BACKEND_SFTP (object);
+
+ g_hash_table_destroy (backend->expected_replies);
+
+ if (backend->command_stream)
+ g_object_unref (backend->command_stream);
+
+ if (backend->reply_stream)
+ g_object_unref (backend->reply_stream);
+
+ if (backend->error_stream)
+ g_object_unref (backend->error_stream);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_sftp_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_sftp_parent_class)->finalize) (object);
+}
+
+static void
+expected_reply_free (ExpectedReply *reply)
+{
+ g_object_unref (reply->job);
+ g_slice_free (ExpectedReply, reply);
+}
+
+static void
+g_vfs_backend_sftp_init (GVfsBackendSftp *backend)
+{
+ backend->expected_replies = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)expected_reply_free);
+}
+
+static void
+look_for_stderr_errors (GVfsBackend *backend, GError **error)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ char *line;
+
+ while (1)
+ {
+ line = g_data_input_stream_read_line (op_backend->error_stream, NULL, NULL, NULL);
+
+ if (line == NULL)
+ {
+ /* Error (real or WOULDBLOCK) or EOF */
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("ssh program unexpectedly exited"));
+ return;
+ }
+
+ if (strstr (line, "Permission denied") != NULL)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Permission denied"));
+ return;
+ }
+ else if (strstr (line, "Name or service not known") != NULL)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_HOST_NOT_FOUND,
+ _("Hostname not known"));
+ return;
+ }
+ else if (strstr (line, "No route to host") != NULL)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_HOST_NOT_FOUND,
+ _("No route to host"));
+ return;
+ }
+ else if (strstr (line, "Connection refused") != NULL)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Connection refused by server"));
+ return;
+ }
+ else if (strstr (line, "Host key verification failed") != NULL)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Host key verification failed"));
+ return;
+ }
+
+ g_free (line);
+ }
+}
+
+static char **
+setup_ssh_commandline (GVfsBackend *backend)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ guint last_arg;
+ gchar **args;
+
+ args = g_new0 (gchar *, 20); /* 20 is enought for now, bump size if code below changes */
+
+ /* Fill in the first few args */
+ last_arg = 0;
+ args[last_arg++] = g_strdup (SSH_PROGRAM);
+
+ if (op_backend->client_vendor == SFTP_VENDOR_OPENSSH)
+ {
+ args[last_arg++] = g_strdup ("-oForwardX11 no");
+ args[last_arg++] = g_strdup ("-oForwardAgent no");
+ args[last_arg++] = g_strdup ("-oClearAllForwardings yes");
+ args[last_arg++] = g_strdup ("-oProtocol 2");
+ args[last_arg++] = g_strdup ("-oNoHostAuthenticationForLocalhost yes");
+#ifndef USE_PTY
+ args[last_arg++] = g_strdup ("-oBatchMode yes");
+#endif
+
+ }
+ else if (op_backend->client_vendor == SFTP_VENDOR_SSH)
+ args[last_arg++] = g_strdup ("-x");
+
+ if (op_backend->port != -1)
+ {
+ args[last_arg++] = g_strdup ("-p");
+ args[last_arg++] = g_strdup_printf ("%d", op_backend->port);
+ }
+
+
+ if (op_backend->user_specified)
+ {
+ args[last_arg++] = g_strdup ("-l");
+ args[last_arg++] = g_strdup (op_backend->user);
+ }
+
+ args[last_arg++] = g_strdup ("-s");
+
+ if (op_backend->client_vendor == SFTP_VENDOR_SSH)
+ {
+ args[last_arg++] = g_strdup ("sftp");
+ args[last_arg++] = g_strdup (op_backend->host);
+ }
+ else
+ {
+ args[last_arg++] = g_strdup (op_backend->host);
+ args[last_arg++] = g_strdup ("sftp");
+ }
+
+ args[last_arg++] = NULL;
+
+ return args;
+}
+
+static gboolean
+spawn_ssh (GVfsBackend *backend,
+ char *args[],
+ pid_t *pid,
+ int *tty_fd,
+ int *stdin_fd,
+ int *stdout_fd,
+ int *stderr_fd,
+ GError **error)
+{
+#ifdef USE_PTY
+ *tty_fd = pty_open(pid, PTY_REAP_CHILD, NULL,
+ args[0], args, NULL,
+ 300, 300,
+ stdin_fd, stdout_fd, stderr_fd);
+ if (*tty_fd == -1)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to spawn ssh program"));
+ return FALSE;
+ }
+#else
+ GError *my_error;
+ GPid gpid;
+
+ *tty_fd = -1;
+
+ my_error = NULL;
+ if (!g_spawn_async_with_pipes (NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
+ &gpid,
+ stdin_fd, stdout_fd, stderr_fd, &my_error))
+ {
+ g_set_error (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to spawn ssh program: %s"), my_error->message);
+ g_error_free (my_error);
+ return FALSE;
+ }
+ *pid = gpid;
+#endif
+
+ return TRUE;
+}
+
+static guint32
+get_new_id (GVfsBackendSftp *backend)
+{
+ return backend->current_id++;
+}
+
+static GDataOutputStream *
+new_command_stream (GVfsBackendSftp *backend, int type)
+{
+ GOutputStream *mem_stream;
+ GDataOutputStream *data_stream;
+ guint32 id;
+
+ mem_stream = g_memory_output_stream_new (NULL, 0, (GReallocFunc)g_realloc, NULL);
+ data_stream = g_data_output_stream_new (mem_stream);
+ g_object_unref (mem_stream);
+
+ g_data_output_stream_put_int32 (data_stream, 0, NULL, NULL); /* LEN */
+ g_data_output_stream_put_byte (data_stream, type, NULL, NULL);
+ if (type != SSH_FXP_INIT)
+ {
+ id = get_new_id (backend);
+ g_data_output_stream_put_uint32 (data_stream, id, NULL, NULL);
+ g_object_set_qdata (G_OBJECT (data_stream), id_q, GUINT_TO_POINTER (id));
+ }
+
+ return data_stream;
+}
+
+static gpointer
+get_data_from_command_stream (GDataOutputStream *command_stream, gsize *len)
+{
+ GOutputStream *mem_stream;
+ gpointer data;
+ guint32 *len_ptr;
+
+ mem_stream = g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (command_stream));
+ *len = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mem_stream));
+ data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mem_stream));
+
+ len_ptr = (guint32 *)data;
+ *len_ptr = GUINT32_TO_BE (*len - 4);
+
+ return data;
+}
+
+static gboolean
+send_command_sync_and_unref_command (GVfsBackendSftp *backend,
+ GDataOutputStream *command_stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gpointer data;
+ gsize len;
+ gsize bytes_written;
+ gboolean res;
+
+ data = get_data_from_command_stream (command_stream, &len);
+
+ res = g_output_stream_write_all (backend->command_stream,
+ data, len,
+ &bytes_written,
+ cancellable, error);
+
+ if (error == NULL && !res)
+ g_warning ("Ignored send_command error\n");
+
+ g_free (data);
+ g_object_unref (command_stream);
+
+ return res;
+}
+
+static gboolean
+wait_for_reply (GVfsBackend *backend, int stdout_fd, GError **error)
+{
+ fd_set ifds;
+ struct timeval tv;
+ int ret;
+
+ FD_ZERO (&ifds);
+ FD_SET (stdout_fd, &ifds);
+
+ tv.tv_sec = 20;
+ tv.tv_usec = 0;
+
+ ret = select (stdout_fd+1, &ifds, NULL, NULL, &tv);
+
+ if (ret <= 0)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+ _("Timed out when logging in"));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static GDataInputStream *
+make_reply_stream (guint8 *data, gsize len)
+{
+ GInputStream *mem_stream;
+ GDataInputStream *data_stream;
+
+ mem_stream = g_memory_input_stream_new_from_data (data, len, g_free);
+ data_stream = g_data_input_stream_new (mem_stream);
+ g_object_unref (mem_stream);
+
+ return data_stream;
+}
+
+static GDataInputStream *
+read_reply_sync (GVfsBackendSftp *backend, gsize *len_out, GError **error)
+{
+ guint32 len;
+ gsize bytes_read;
+ GByteArray *array;
+ guint8 *data;
+
+ if (!g_input_stream_read_all (backend->reply_stream,
+ &len, 4,
+ &bytes_read, NULL, error))
+ return NULL;
+
+ /* Make sure we handle ssh exiting early, e.g. if no further
+ authentication methods */
+ if (bytes_read == 0)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("ssh program unexpectedly exited"));
+ return NULL;
+ }
+
+ len = GUINT32_FROM_BE (len);
+
+ array = g_byte_array_sized_new (len);
+
+ if (!g_input_stream_read_all (backend->reply_stream,
+ array->data, len,
+ &bytes_read, NULL, error))
+ {
+ g_byte_array_free (array, TRUE);
+ return NULL;
+ }
+
+ if (len_out)
+ *len_out = len;
+
+ data = array->data;
+ g_byte_array_free (array, FALSE);
+
+ return make_reply_stream (data, len);
+}
+
+static void
+put_string (GDataOutputStream *stream, const char *str)
+{
+ g_data_output_stream_put_uint32 (stream, strlen (str), NULL, NULL);
+ g_data_output_stream_put_string (stream, str, NULL, NULL);
+}
+
+static void
+put_data_buffer (GDataOutputStream *stream, DataBuffer *buffer)
+{
+ g_data_output_stream_put_uint32 (stream, buffer->size, NULL, NULL);
+ g_output_stream_write_all (G_OUTPUT_STREAM (stream),
+ buffer->data, buffer->size,
+ NULL,
+ NULL, NULL);
+}
+
+static char *
+read_string (GDataInputStream *stream, gsize *len_out)
+{
+ guint32 len;
+ char *data;
+ GError *error;
+
+ error = NULL;
+ len = g_data_input_stream_read_uint32 (stream, NULL, &error);
+ if (error)
+ {
+ g_error_free (error);
+ return NULL;
+ }
+
+ data = g_malloc (len + 1);
+
+ if (!g_input_stream_read_all (G_INPUT_STREAM (stream), data, len, NULL, NULL, NULL))
+ {
+ g_free (data);
+ return NULL;
+ }
+
+ data[len] = 0;
+
+ if (len_out)
+ *len_out = len;
+
+ return data;
+}
+
+static DataBuffer *
+read_data_buffer (GDataInputStream *stream)
+{
+ DataBuffer *buffer;
+
+ buffer = g_slice_new (DataBuffer);
+ buffer->data = (guchar *)read_string (stream, &buffer->size);
+
+ return buffer;
+}
+
+static gboolean
+get_hostname_and_fingerprint_from_line (const gchar *buffer,
+ gchar **hostname_out,
+ gchar **fingerprint_out)
+{
+ gchar *pos;
+ gchar *startpos;
+ gchar *endpos;
+ gchar *hostname = NULL;
+ gchar *fingerprint = NULL;
+
+ if (g_str_has_prefix (buffer, "The authenticity of host '"))
+ {
+ /* OpenSSH */
+ pos = strchr (&buffer[26], '\'');
+ if (pos == NULL)
+ return FALSE;
+
+ hostname = g_strndup (&buffer[26], pos - (&buffer[26]));
+
+ startpos = strstr (pos, " key fingerprint is ");
+ if (startpos == NULL)
+ {
+ g_free (hostname);
+ return FALSE;
+ }
+
+ startpos = startpos + 20;
+ endpos = strchr (startpos, '.');
+ if (endpos == NULL)
+ {
+ g_free (hostname);
+ return FALSE;
+ }
+
+ fingerprint = g_strndup (startpos, endpos - startpos);
+ }
+ else if (strstr (buffer, "Key fingerprint:") != NULL)
+ {
+ /* SSH.com*/
+ startpos = strstr (buffer, "Key fingerprint:");
+ if (startpos == NULL)
+ {
+ g_free (hostname);
+ return FALSE;
+ }
+
+ startpos = startpos + 18;
+ endpos = strchr (startpos, '\r');
+ fingerprint = g_strndup (startpos, endpos - startpos);
+ }
+
+ *hostname_out = hostname;
+ *fingerprint_out = fingerprint;
+
+ return TRUE;
+}
+
+static const gchar *
+get_authtype_from_password_line (const char *password_line)
+{
+ return g_str_has_prefix (password_line, "Enter passphrase for key") ?
+ "publickey" : "password";
+}
+
+static char *
+get_object_from_password_line (const char *password_line)
+{
+ char *chr, *ptr, *object = NULL;
+
+ if (g_str_has_prefix (password_line, "Enter passphrase for key"))
+ {
+ ptr = strchr (password_line, '\'');
+ if (ptr != NULL)
+ {
+ ptr += 1;
+ chr = strchr (ptr, '\'');
+ if (chr != NULL)
+ {
+ object = g_strndup (ptr, chr - ptr);
+ }
+ else
+ {
+ object = g_strdup (ptr);
+ }
+ }
+ }
+ return object;
+}
+
+static gboolean
+handle_login (GVfsBackend *backend,
+ GMountSource *mount_source,
+ int tty_fd, int stdout_fd, int stderr_fd,
+ GError **error)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GInputStream *prompt_stream;
+ GOutputStream *reply_stream;
+ fd_set ifds;
+ struct timeval tv;
+ int ret;
+ int prompt_fd;
+ char buffer[1024];
+ gsize len;
+ gboolean aborted = FALSE;
+ gboolean ret_val;
+ char *new_password = NULL;
+ char *new_user = NULL;
+ GPasswordSave password_save = G_PASSWORD_SAVE_NEVER;
+ gsize bytes_written;
+ gboolean password_in_keyring = FALSE;
+ const gchar *authtype = NULL;
+ gchar *object = NULL;
+
+ if (op_backend->client_vendor == SFTP_VENDOR_SSH)
+ prompt_fd = stderr_fd;
+ else
+ prompt_fd = tty_fd;
+
+ prompt_stream = g_unix_input_stream_new (prompt_fd, FALSE);
+ reply_stream = g_unix_output_stream_new (tty_fd, FALSE);
+
+ ret_val = TRUE;
+ while (1)
+ {
+ FD_ZERO (&ifds);
+ FD_SET (stdout_fd, &ifds);
+ FD_SET (prompt_fd, &ifds);
+
+ tv.tv_sec = 20;
+ tv.tv_usec = 0;
+
+ ret = select (MAX (stdout_fd, prompt_fd)+1, &ifds, NULL, NULL, &tv);
+
+ if (ret <= 0)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+ _("Timed out when logging in"));
+ ret_val = FALSE;
+ break;
+ }
+
+ if (FD_ISSET (stdout_fd, &ifds))
+ break; /* Got reply to initial INIT request */
+
+ g_assert (FD_ISSET (prompt_fd, &ifds));
+
+
+ len = g_input_stream_read (prompt_stream,
+ buffer, sizeof (buffer) - 1,
+ NULL, error);
+
+ if (len == -1)
+ {
+ ret_val = FALSE;
+ break;
+ }
+
+ buffer[len] = 0;
+
+ /*
+ * If the input URI contains a username
+ * if the input URI contains a password, we attempt one login and return GNOME_VFS_ERROR_ACCESS_DENIED on failure.
+ * if the input URI contains no password, we query the user until he provides a correct one, or he cancels.
+ *
+ * If the input URI contains no username
+ * (a) the user is queried for a user name and a password, with the default login being his
+ * local login name.
+ *
+ * (b) if the user decides to change his remote login name, we go to tty_retry because we need a
+ * new SSH session, attempting one login with his provided credentials, and if that fails proceed
+ * with (a), but use his desired remote login name as default.
+ *
+ * The "password" variable is only used for the very first login attempt,
+ * or for the first re-login attempt when the user decided to change his name.
+ * Otherwise, we "new_password" and "new_user_name" is used, as output variable
+ * for user and keyring input.
+ */
+ if (g_str_has_suffix (buffer, "password: ") ||
+ g_str_has_suffix (buffer, "Password: ") ||
+ g_str_has_suffix (buffer, "Password:") ||
+ g_str_has_prefix (buffer, "Password for ") ||
+ g_str_has_prefix (buffer, "Enter Kerberos password") ||
+ g_str_has_prefix (buffer, "Enter passphrase for key"))
+ {
+ authtype = get_authtype_from_password_line (buffer);
+ object = get_object_from_password_line (buffer);
+
+ /* If password is in keyring at this point is because it failed */
+ if (!op_backend->tmp_password && (password_in_keyring ||
+ !g_vfs_keyring_lookup_password (op_backend->user,
+ op_backend->host,
+ NULL,
+ "sftp",
+ object,
+ authtype,
+ op_backend->port != -1 ?
+ op_backend->port
+ :
+ 0,
+ NULL,
+ NULL,
+ &new_password)))
+ {
+ GAskPasswordFlags flags = G_ASK_PASSWORD_NEED_PASSWORD;
+
+ if (g_vfs_keyring_is_available ())
+ flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+ if (strcmp (authtype, "password") == 0 &&
+ !op_backend->user_specified)
+ flags |= G_ASK_PASSWORD_NEED_USERNAME;
+
+ g_free (new_password);
+
+ if (!g_mount_source_ask_password (mount_source,
+ strcmp (authtype, "publickey") == 0 ?
+ _("Enter passphrase for key")
+ :
+ _("Enter password"),
+ op_backend->user,
+ NULL,
+ flags,
+ &aborted,
+ &new_password,
+ &new_user,
+ NULL,
+ NULL,
+ &password_save) ||
+ aborted)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Password dialog cancelled"));
+ ret_val = FALSE;
+ break;
+ }
+ }
+ else if (op_backend->tmp_password)
+ {
+ /* I already a have a password of a previous login attempt
+ * that failed because the user provided a new user name
+ */
+ new_password = op_backend->tmp_password;
+ op_backend->tmp_password = NULL;
+ }
+ else
+ password_in_keyring = TRUE;
+
+ if (new_user &&
+ (op_backend->user == NULL ||
+ strcmp (new_user, op_backend->user) != 0))
+ {
+ g_free (op_backend->user);
+ op_backend->user = new_user;
+
+ op_backend->user_specified = TRUE;
+
+ g_free (op_backend->tmp_password);
+ op_backend->tmp_password = new_password;
+ new_password = NULL;
+
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Invalid user name");
+ ret_val = FALSE;
+ break;
+ }
+ else if (new_user)
+ {
+ g_free (new_user);
+ }
+
+ if (new_password == NULL)
+ {
+ /* This really should not happen, but was seen as bug #569203
+ * avoid crash and ask for info
+ */
+ g_warning ("Got NULL password but no error in sftp login request. "
+ "This should not happen, if you can reproduce this, please "
+ "add information to http://bugzilla.gnome.org/show_bug.cgi?id=569203");
+ new_password = g_strdup ("");
+ }
+
+ if (!g_output_stream_write_all (reply_stream,
+ new_password, strlen (new_password),
+ &bytes_written,
+ NULL, NULL) ||
+ !g_output_stream_write_all (reply_stream,
+ "\n", 1,
+ &bytes_written,
+ NULL, NULL))
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Can't send password"));
+ ret_val = FALSE;
+ break;
+ }
+ }
+ else if (g_str_has_prefix (buffer, "The authenticity of host '") ||
+ strstr (buffer, "Key fingerprint:") != NULL)
+ {
+ const gchar *choices[] = {_("Log In Anyway"), _("Cancel Login")};
+ const gchar *v_choices = (const gchar *)choices;
+ const gchar *choice_string;
+ gchar *hostname = NULL;
+ gchar *fingerprint = NULL;
+ gint choice;
+ gchar *message;
+
+ get_hostname_and_fingerprint_from_line (buffer, &hostname, &fingerprint);
+
+ message = g_strdup_printf (_("The identity of the remote computer (%s) is unknown.\n"
+ "This happens when you log in to a computer the first time.\n\n"
+ "The identity sent by the remote computer is %s. "
+ "If you want to be absolutely sure it is safe to continue, "
+ "contact the system administrator."),
+ hostname ? hostname : op_backend->host, fingerprint);
+
+ g_free (hostname);
+ g_free (fingerprint);
+
+ if (!g_mount_source_ask_question (mount_source,
+ message,
+ &v_choices,
+ 2,
+ &aborted,
+ &choice) ||
+ aborted)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Login dialog cancelled"));
+ g_free (message);
+ ret_val = FALSE;
+ break;
+ }
+ g_free (message);
+
+ choice_string = (choice == 0) ? "yes" : "no";
+ if (!g_output_stream_write_all (reply_stream,
+ choice_string,
+ strlen (choice_string),
+ &bytes_written,
+ NULL, NULL) ||
+ !g_output_stream_write_all (reply_stream,
+ "\n", 1,
+ &bytes_written,
+ NULL, NULL))
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Can't send host identity confirmation"));
+ ret_val = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (ret_val)
+ {
+ /* Login succeed, save password in keyring */
+ g_vfs_keyring_save_password (op_backend->user,
+ op_backend->host,
+ NULL,
+ "sftp",
+ object,
+ authtype,
+ op_backend->port != -1 ?
+ op_backend->port
+ :
+ 0,
+ new_password,
+ password_save);
+ }
+
+ g_free (object);
+ g_free (new_password);
+ g_object_unref (prompt_stream);
+ g_object_unref (reply_stream);
+ return ret_val;
+}
+
+static void
+fail_jobs_and_die (GVfsBackendSftp *backend, GError *error)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, backend->expected_replies);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ ExpectedReply *expected_reply = (ExpectedReply *) value;
+ g_vfs_job_failed_from_error (expected_reply->job, error);
+ }
+
+ g_error_free (error);
+
+ _exit (1);
+}
+
+static void
+check_input_stream_read_result (GVfsBackendSftp *backend, gssize res, GError *error)
+{
+ if (G_UNLIKELY (res <= 0))
+ {
+ if (res == 0 || error == NULL)
+ {
+ g_clear_error (&error);
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Internal error: %s"),
+ res == 0 ? "The underlying ssh process died" : "Unkown Error");
+ }
+
+ fail_jobs_and_die (backend, error);
+ }
+}
+
+static void read_reply_async (GVfsBackendSftp *backend);
+
+static void
+read_reply_async_got_data (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GVfsBackendSftp *backend = user_data;
+ gssize res;
+ GDataInputStream *reply;
+ ExpectedReply *expected_reply;
+ guint32 id;
+ int type;
+ GError *error;
+
+ error = NULL;
+ res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), result, &error);
+
+ check_input_stream_read_result (backend, res, error);
+
+ backend->reply_size_read += res;
+
+ if (backend->reply_size_read < backend->reply_size)
+ {
+ g_input_stream_read_async (backend->reply_stream,
+ backend->reply + backend->reply_size_read, backend->reply_size - backend->reply_size_read,
+ 0, NULL, read_reply_async_got_data, backend);
+ return;
+ }
+
+ reply = make_reply_stream (backend->reply, backend->reply_size);
+ backend->reply = NULL;
+
+ type = g_data_input_stream_read_byte (reply, NULL, NULL);
+ id = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ expected_reply = g_hash_table_lookup (backend->expected_replies, GINT_TO_POINTER (id));
+ if (expected_reply)
+ {
+ if (expected_reply->callback != NULL)
+ (expected_reply->callback) (backend, type, reply, backend->reply_size,
+ expected_reply->job, expected_reply->user_data);
+ g_hash_table_remove (backend->expected_replies, GINT_TO_POINTER (id));
+ }
+ else
+ g_warning ("Got unhandled reply of size %"G_GUINT32_FORMAT" for id %"G_GUINT32_FORMAT"\n", backend->reply_size, id);
+
+ g_object_unref (reply);
+
+ read_reply_async (backend);
+
+}
+
+static void
+read_reply_async_got_len (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GVfsBackendSftp *backend = user_data;
+ gssize res;
+ GError *error;
+
+ error = NULL;
+ res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), result, &error);
+
+ check_input_stream_read_result (backend, res, error);
+
+ backend->reply_size_read += res;
+
+ if (backend->reply_size_read < 4)
+ {
+ g_input_stream_read_async (backend->reply_stream,
+ &backend->reply_size + backend->reply_size_read, 4 - backend->reply_size_read,
+ 0, NULL, read_reply_async_got_len, backend);
+ return;
+ }
+ backend->reply_size = GUINT32_FROM_BE (backend->reply_size);
+
+ backend->reply_size_read = 0;
+ backend->reply = g_malloc (backend->reply_size);
+ g_input_stream_read_async (backend->reply_stream,
+ backend->reply, backend->reply_size,
+ 0, NULL, read_reply_async_got_data, backend);
+}
+
+static void
+read_reply_async (GVfsBackendSftp *backend)
+{
+ backend->reply_size_read = 0;
+ g_input_stream_read_async (backend->reply_stream,
+ &backend->reply_size, 4,
+ 0, NULL, read_reply_async_got_len, backend);
+}
+
+static void send_command (GVfsBackendSftp *backend);
+
+static void
+send_command_data (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GVfsBackendSftp *backend = user_data;
+ gssize res;
+ DataBuffer *buffer;
+
+ res = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object), result, NULL);
+
+ if (res <= 0)
+ {
+ /* TODO: unmount, etc */
+ g_warning ("Error sending command");
+ return;
+ }
+
+ buffer = backend->command_queue->data;
+
+ backend->command_bytes_written += res;
+
+ if (backend->command_bytes_written < buffer->size)
+ {
+ g_output_stream_write_async (backend->command_stream,
+ buffer->data + backend->command_bytes_written,
+ buffer->size - backend->command_bytes_written,
+ 0,
+ NULL,
+ send_command_data,
+ backend);
+ return;
+ }
+
+ data_buffer_free (buffer);
+
+ backend->command_queue = g_list_delete_link (backend->command_queue, backend->command_queue);
+
+ if (backend->command_queue != NULL)
+ send_command (backend);
+}
+
+static void
+send_command (GVfsBackendSftp *backend)
+{
+ DataBuffer *buffer;
+
+ buffer = backend->command_queue->data;
+
+ backend->command_bytes_written = 0;
+ g_output_stream_write_async (backend->command_stream,
+ buffer->data,
+ buffer->size,
+ 0,
+ NULL,
+ send_command_data,
+ backend);
+}
+
+static void
+expect_reply (GVfsBackendSftp *backend,
+ guint32 id,
+ ReplyCallback callback,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ ExpectedReply *expected;
+
+ expected = g_slice_new (ExpectedReply);
+ expected->callback = callback;
+ expected->job = g_object_ref (job);
+ expected->user_data = user_data;
+
+ g_hash_table_replace (backend->expected_replies, GINT_TO_POINTER (id), expected);
+}
+
+static DataBuffer *
+data_buffer_new (guchar *data, gsize len)
+{
+ DataBuffer *buffer;
+
+ buffer = g_slice_new (DataBuffer);
+ buffer->data = data;
+ buffer->size = len;
+
+ return buffer;
+}
+
+static void
+queue_command_buffer (GVfsBackendSftp *backend,
+ DataBuffer *buffer)
+{
+ gboolean first;
+
+ first = backend->command_queue == NULL;
+
+ backend->command_queue = g_list_append (backend->command_queue, buffer);
+
+ if (first)
+ send_command (backend);
+}
+
+static void
+queue_command_stream_and_free (GVfsBackendSftp *backend,
+ GDataOutputStream *command_stream,
+ ReplyCallback callback,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ gpointer data;
+ gsize len;
+ DataBuffer *buffer;
+ guint32 id;
+
+ id = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (command_stream), id_q));
+ data = get_data_from_command_stream (command_stream, &len);
+
+ buffer = data_buffer_new (data, len);
+ g_object_unref (command_stream);
+
+ expect_reply (backend, id, callback, job, user_data);
+ queue_command_buffer (backend, buffer);
+}
+
+
+static void
+multi_request_cb (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply_stream,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ MultiReply *reply;
+ MultiRequest *request;
+ int i;
+
+ reply = user_data;
+ request = reply->request;
+
+ reply->type = reply_type;
+ reply->data = g_object_ref (reply_stream);
+ reply->data_len = len;
+
+ if (--request->n_outstanding == 0)
+ {
+ /* Call callback */
+ if (request->callback != NULL)
+ (request->callback) (backend,
+ request->replies,
+ request->n_replies,
+ job,
+ request->user_data);
+
+ /* Free request data */
+
+ for (i = 0; i < request->n_replies; i++)
+ {
+ reply = &request->replies[i];
+ if (reply->data)
+ g_object_unref (reply->data);
+ }
+ g_free (request->replies);
+
+ g_free (request);
+
+ }
+}
+
+static void
+queue_command_streams_and_free (GVfsBackendSftp *backend,
+ GDataOutputStream **commands,
+ int n_commands,
+ MultiReplyCallback callback,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ MultiRequest *data;
+ MultiReply *reply;
+
+ int i;
+
+ data = g_new0 (MultiRequest, 1);
+
+ data->user_data = user_data;
+ data->n_replies = n_commands;
+ data->n_outstanding = n_commands;
+ data->replies = g_new0 (MultiReply, n_commands);
+ data->callback = callback;
+
+ for (i = 0; i < n_commands; i++)
+ {
+ reply = &data->replies[i];
+ reply->request = data;
+ queue_command_stream_and_free (backend,
+ commands[i],
+ multi_request_cb,
+ job,
+ reply);
+ }
+}
+
+static gboolean
+get_uid_sync (GVfsBackendSftp *backend)
+{
+ GDataOutputStream *command;
+ GDataInputStream *reply;
+ int type;
+
+ command = new_command_stream (backend, SSH_FXP_STAT);
+ put_string (command, ".");
+ send_command_sync_and_unref_command (backend, command, NULL, NULL);
+
+ reply = read_reply_sync (backend, NULL, NULL);
+ if (reply == NULL)
+ return FALSE;
+
+ type = g_data_input_stream_read_byte (reply, NULL, NULL);
+ /*id =*/ (void) g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ /* On error, set uid to -1 and ignore */
+ backend->my_uid = (guint32)-1;
+ backend->my_gid = (guint32)-1;
+ if (type == SSH_FXP_ATTRS)
+ {
+ GFileInfo *info;
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL, reply, NULL);
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID))
+ {
+ /* Both are always set if set */
+ backend->my_uid = g_file_info_get_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_UNIX_UID);
+ backend->my_gid = g_file_info_get_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_UNIX_GID);
+ }
+
+ g_object_unref (info);
+ }
+
+ g_object_unref (reply);
+
+ return TRUE;
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ gchar **args; /* Enough for now, extend if you add more args */
+ pid_t pid;
+ int tty_fd, stdout_fd, stdin_fd, stderr_fd;
+ GError *error;
+ GInputStream *is;
+ GDataOutputStream *command;
+ GDataInputStream *reply;
+ gboolean res;
+ GMountSpec *sftp_mount_spec;
+ char *extension_name, *extension_data;
+ char *display_name;
+
+ args = setup_ssh_commandline (backend);
+
+ error = NULL;
+ if (!spawn_ssh (backend,
+ args, &pid,
+ &tty_fd, &stdin_fd, &stdout_fd, &stderr_fd,
+ &error))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_strfreev (args);
+ return;
+ }
+
+ g_strfreev (args);
+
+ op_backend->command_stream = g_unix_output_stream_new (stdin_fd, TRUE);
+
+ command = new_command_stream (op_backend, SSH_FXP_INIT);
+ g_data_output_stream_put_int32 (command,
+ SSH_FILEXFER_VERSION, NULL, NULL);
+ send_command_sync_and_unref_command (op_backend, command, NULL, NULL);
+
+ if (tty_fd == -1)
+ res = wait_for_reply (backend, stdout_fd, &error);
+ else
+ res = handle_login (backend, mount_source, tty_fd, stdout_fd, stderr_fd, &error);
+
+ if (!res)
+ {
+ if (error->code == G_IO_ERROR_INVALID_ARGUMENT)
+ {
+ /* New username provided by the user,
+ * we need to re-spawn the ssh command
+ */
+ g_error_free (error);
+ do_mount (backend, job, mount_spec, mount_source, is_automount);
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+
+ return;
+ }
+
+ op_backend->reply_stream = g_unix_input_stream_new (stdout_fd, TRUE);
+
+ make_fd_nonblocking (stderr_fd);
+ is = g_unix_input_stream_new (stderr_fd, TRUE);
+ op_backend->error_stream = g_data_input_stream_new (is);
+ g_object_unref (is);
+
+ reply = read_reply_sync (op_backend, NULL, NULL);
+ if (reply == NULL)
+ {
+ look_for_stderr_errors (backend, &error);
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_data_input_stream_read_byte (reply, NULL, NULL) != SSH_FXP_VERSION)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Protocol error"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ op_backend->protocol_version = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ while ((extension_name = read_string (reply, NULL)) != NULL)
+ {
+ extension_data = read_string (reply, NULL);
+ if (extension_data)
+ {
+ /* TODO: Do something with this */
+ }
+ g_free (extension_name);
+ g_free (extension_data);
+ }
+
+ g_object_unref (reply);
+
+ if (!get_uid_sync (op_backend))
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Protocol error"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ read_reply_async (op_backend);
+
+ sftp_mount_spec = g_mount_spec_new ("sftp");
+ if (op_backend->user_specified)
+ g_mount_spec_set (sftp_mount_spec, "user", op_backend->user);
+ g_mount_spec_set (sftp_mount_spec, "host", op_backend->host);
+ if (op_backend->port != -1)
+ {
+ char *v;
+ v = g_strdup_printf ("%d", op_backend->port);
+ g_mount_spec_set (sftp_mount_spec, "port", v);
+ g_free (v);
+ }
+
+ g_vfs_backend_set_mount_spec (backend, sftp_mount_spec);
+ g_mount_spec_unref (sftp_mount_spec);
+
+ if (op_backend->user_specified)
+ /* Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>" */
+ display_name = g_strdup_printf (_("sftp for %s on %s"), op_backend->user, op_backend->host);
+ else
+ /* Translators: This is the name of an sftp share, like "sftp on <hostname>" */
+ display_name = g_strdup_printf (_("sftp on %s"), op_backend->host);
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+
+ /* checks for /etc/favicon.png */
+ setup_icon (op_backend, job);
+
+ /* NOTE: job_succeeded called async from setup_icon reply */
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ const char *user, *host, *port;
+
+ op_backend->client_vendor = get_sftp_client_vendor ();
+
+ if (op_backend->client_vendor == SFTP_VENDOR_INVALID)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to find supported ssh command"));
+ return TRUE;
+ }
+
+ host = g_mount_spec_get (mount_spec, "host");
+
+ if (host == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("No hostname specified"));
+ return TRUE;
+ }
+
+ port = g_mount_spec_get (mount_spec, "port");
+ op_backend->port = -1;
+ if (port != NULL)
+ {
+ int p = atoi (port);
+ if (p != 22)
+ op_backend->port = p;
+ }
+
+ user = g_mount_spec_get (mount_spec, "user");
+
+ op_backend->host = g_strdup (host);
+ op_backend->user = g_strdup (user);
+ if (op_backend->user)
+ op_backend->user_specified = TRUE;
+
+ return FALSE;
+}
+
+static int
+io_error_code_for_sftp_error (guint32 code, int failure_error)
+{
+ int error_code;
+
+ error_code = G_IO_ERROR_FAILED;
+
+ switch (code)
+ {
+ default:
+ case SSH_FX_EOF:
+ case SSH_FX_BAD_MESSAGE:
+ case SSH_FX_NO_CONNECTION:
+ case SSH_FX_CONNECTION_LOST:
+ break;
+
+ case SSH_FX_FAILURE:
+ error_code = failure_error;
+ break;
+
+ case SSH_FX_NO_SUCH_FILE:
+ error_code = G_IO_ERROR_NOT_FOUND;
+ break;
+
+ case SSH_FX_PERMISSION_DENIED:
+ error_code = G_IO_ERROR_PERMISSION_DENIED;
+ break;
+
+ case SSH_FX_OP_UNSUPPORTED:
+ error_code = G_IO_ERROR_NOT_SUPPORTED;
+ break;
+ }
+ return error_code;
+}
+
+static gboolean
+error_from_status (GVfsJob *job,
+ GDataInputStream *reply,
+ int failure_error,
+ int allowed_sftp_error,
+ GError **error)
+{
+ guint32 code;
+ gint error_code;
+ char *message;
+
+ if (failure_error == -1)
+ failure_error = G_IO_ERROR_FAILED;
+
+ code = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ if (code == SSH_FX_OK ||
+ (allowed_sftp_error != -1 &&
+ code == allowed_sftp_error))
+ return TRUE;
+
+ if (error)
+ {
+ error_code = io_error_code_for_sftp_error (code, failure_error);
+ message = read_string (reply, NULL);
+ if (message == NULL)
+ message = g_strdup ("Unknown reason");
+
+ *error = g_error_new_literal (G_IO_ERROR, error_code, message);
+ g_free (message);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+failure_from_status (GVfsJob *job,
+ GDataInputStream *reply,
+ int failure_error,
+ int allowed_sftp_error)
+{
+ GError *error;
+
+ error = NULL;
+ if (error_from_status (job, reply, failure_error, allowed_sftp_error, &error))
+ return TRUE;
+ else
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ }
+ return FALSE;
+}
+
+
+static gboolean
+result_from_status (GVfsJob *job,
+ GDataInputStream *reply,
+ int failure_error,
+ int allowed_sftp_error)
+{
+ gboolean res;
+
+ res = failure_from_status (job, reply,
+ failure_error,
+ allowed_sftp_error);
+ if (res)
+ g_vfs_job_succeeded (job);
+
+ return res;
+}
+
+static void
+set_access_attributes (GFileInfo *info,
+ guint32 perm)
+{
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
+ perm & 0x4);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ perm & 0x2);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
+ perm & 0x1);
+}
+
+
+static void
+parse_attributes (GVfsBackendSftp *backend,
+ GFileInfo *info,
+ const char *basename,
+ GDataInputStream *reply,
+ GFileAttributeMatcher *matcher)
+{
+ guint32 flags;
+ GFileType type;
+ guint32 uid, gid;
+ guint32 mode;
+ gboolean has_uid, free_mimetype;
+ char *mimetype;
+ GIcon *icon;
+
+ flags = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ if (basename != NULL && basename[0] == '.')
+ g_file_info_set_is_hidden (info, TRUE);
+
+ if (basename != NULL)
+ g_file_info_set_name (info, basename);
+ else
+ g_file_info_set_name (info, "/");
+
+ if (basename != NULL && basename[strlen (basename) -1] == '~')
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, TRUE);
+
+ if (flags & SSH_FILEXFER_ATTR_SIZE)
+ {
+ guint64 size = g_data_input_stream_read_uint64 (reply, NULL, NULL);
+ g_file_info_set_size (info, size);
+ }
+
+ has_uid = FALSE;
+ uid = gid = 0; /* Avoid warnings */
+ if (flags & SSH_FILEXFER_ATTR_UIDGID)
+ {
+ has_uid = TRUE;
+ uid = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
+ gid = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
+ }
+
+ type = G_FILE_TYPE_UNKNOWN;
+
+ if (flags & SSH_FILEXFER_ATTR_PERMISSIONS)
+ {
+ mode = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, mode);
+
+ mimetype = NULL;
+ if (S_ISREG (mode))
+ type = G_FILE_TYPE_REGULAR;
+ else if (S_ISDIR (mode))
+ {
+ type = G_FILE_TYPE_DIRECTORY;
+ mimetype = "inode/directory";
+ }
+ else if (S_ISFIFO (mode))
+ {
+ type = G_FILE_TYPE_SPECIAL;
+ mimetype = "inode/fifo";
+ }
+ else if (S_ISSOCK (mode))
+ {
+ type = G_FILE_TYPE_SPECIAL;
+ mimetype = "inode/socket";
+ }
+ else if (S_ISCHR (mode))
+ {
+ type = G_FILE_TYPE_SPECIAL;
+ mimetype = "inode/chardevice";
+ }
+ else if (S_ISBLK (mode))
+ {
+ type = G_FILE_TYPE_SPECIAL;
+ mimetype = "inode/blockdevice";
+ }
+ else if (S_ISLNK (mode))
+ {
+ type = G_FILE_TYPE_SYMBOLIC_LINK;
+ g_file_info_set_is_symlink (info, TRUE);
+ mimetype = "inode/symlink";
+ }
+
+ free_mimetype = FALSE;
+ if (mimetype == NULL)
+ {
+ if (basename)
+ {
+ mimetype = g_content_type_guess (basename, NULL, 0, NULL);
+ free_mimetype = TRUE;
+ }
+ else
+ mimetype = "application/octet-stream";
+ }
+
+ g_file_info_set_content_type (info, mimetype);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, mimetype);
+
+ if (g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_ICON))
+ {
+ icon = NULL;
+ if (S_ISDIR(mode))
+ icon = g_themed_icon_new ("folder");
+ else if (mimetype)
+ icon = g_content_type_get_icon (mimetype);
+
+ if (icon == NULL)
+ icon = g_themed_icon_new ("text-x-generic");
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+
+
+ if (free_mimetype)
+ g_free (mimetype);
+
+ if (has_uid && backend->my_uid != (guint32)-1)
+ {
+ if (uid == backend->my_uid)
+ set_access_attributes (info, (mode >> 6) & 0x7);
+ else if (gid == backend->my_gid)
+ set_access_attributes (info, (mode >> 3) & 0x7);
+ else
+ set_access_attributes (info, (mode >> 0) & 0x7);
+ }
+
+ }
+
+ g_file_info_set_file_type (info, type);
+
+ if (flags & SSH_FILEXFER_ATTR_ACMODTIME)
+ {
+ guint32 v;
+ char *etag;
+
+ v = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, v);
+ v = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, v);
+
+ etag = g_strdup_printf ("%lu", (long unsigned int)v);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, etag);
+ g_free (etag);
+ }
+
+ if (flags & SSH_FILEXFER_ATTR_EXTENDED)
+ {
+ guint32 count, i;
+ char *name, *val;
+ count = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ for (i = 0; i < count; i++)
+ {
+ name = read_string (reply, NULL);
+ val = read_string (reply, NULL);
+
+ g_free (name);
+ g_free (val);
+ }
+ }
+
+ /* We use the same setting as for local files. Can't really
+ * do better, since there is no way in this version of sftp to find out
+ * the remote charset encoding
+ */
+ if (g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
+ {
+ if (basename != NULL)
+ {
+ char *display_name = g_filename_display_name (basename);
+
+ if (strstr (display_name, "\357\277\275") != NULL)
+ {
+ char *p = display_name;
+ display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL);
+ g_free (p);
+ }
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+ else
+ {
+ char *name;
+
+
+ /* Translators: This is the name of the root of an sftp share, like "/ on <hostname>" */
+ name = g_strdup_printf (_("/ on %s"), G_VFS_BACKEND_SFTP (backend)->host);
+ g_file_info_set_display_name (info, name);
+ g_free (name);
+ }
+ }
+
+ if (basename != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME))
+ {
+ char *edit_name = g_filename_display_name (basename);
+ g_file_info_set_edit_name (info, edit_name);
+ g_free (edit_name);
+ }
+}
+
+static SftpHandle *
+sftp_handle_new (GDataInputStream *reply)
+{
+ SftpHandle *handle;
+
+ handle = g_slice_new0 (SftpHandle);
+ handle->raw_handle = read_data_buffer (reply);
+ handle->offset = 0;
+
+ return handle;
+}
+
+static void
+sftp_handle_free (SftpHandle *handle)
+{
+ data_buffer_free (handle->raw_handle);
+ g_free (handle->filename);
+ g_free (handle->tempname);
+ g_slice_free (SftpHandle, handle);
+}
+
+static void
+open_stat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (g_vfs_job_is_finished (job))
+ {
+ /* Handled in stat reply */
+ return;
+ }
+
+ if (reply_type == SSH_FXP_ATTRS)
+ {
+ GFileType type;
+ GFileInfo *info = g_file_info_new ();
+
+ parse_attributes (backend, info, NULL,
+ reply, NULL);
+ type = g_file_info_get_file_type (info);
+ g_object_unref (info);
+
+ if (type == G_FILE_TYPE_DIRECTORY)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("File is directory"));
+ return;
+ }
+ }
+
+ if (GPOINTER_TO_INT (G_VFS_JOB(job)->backend_data) == 1)
+ {
+ /* We ran the read_reply and it was a generic failure */
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Failure"));
+ }
+}
+
+static void
+open_for_read_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ if (g_vfs_job_is_finished (job))
+ {
+ /* Handled in stat reply */
+
+ /* Normally this should not happen as we
+ sent an is_dir error. But i guess we can
+ race */
+ if (reply_type == SSH_FXP_HANDLE)
+ {
+ GDataOutputStream *command;
+ DataBuffer *bhandle;
+
+ bhandle = read_data_buffer (reply);
+
+ command = new_command_stream (backend, SSH_FXP_CLOSE);
+ put_data_buffer (command, bhandle);
+ queue_command_stream_and_free (backend, command, NULL, G_VFS_JOB (job), NULL);
+
+ data_buffer_free (bhandle);
+ }
+
+ return;
+ }
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ if (failure_from_status (job,
+ reply,
+ -1,
+ SSH_FX_FAILURE))
+ {
+ /* Unknown failure type, mark that we got this and
+ return result from stat result */
+ G_VFS_JOB(job)->backend_data = GINT_TO_POINTER (1);
+ }
+
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+
+ g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), handle);
+ g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), TRUE);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ G_VFS_JOB(job)->backend_data = GINT_TO_POINTER (0);
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_STAT);
+ put_string (command, filename);
+ queue_command_stream_and_free (op_backend, command, open_stat_reply, G_VFS_JOB (job), NULL);
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPEN);
+ put_string (command, filename);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_READ, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL); /* Attr flags */
+
+ queue_command_stream_and_free (op_backend, command, open_for_read_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+try_open_icon_for_read (GVfsBackend *backend,
+ GVfsJobOpenIconForRead *job,
+ const char *icon_id)
+{
+ if (g_str_has_prefix (icon_id, "favicon:"))
+ {
+ return try_open_for_read (backend,
+ G_VFS_JOB_OPEN_FOR_READ (job),
+ icon_id + sizeof ("favicon:") -1);
+ }
+
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid icon_id '%s' in OpenIconForRead"),
+ icon_id);
+ return TRUE;
+}
+
+static void
+read_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+ guint32 count;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, SSH_FX_EOF);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_DATA)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ count = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ if (!g_input_stream_read_all (G_INPUT_STREAM (reply),
+ G_VFS_JOB_READ (job)->buffer, count,
+ NULL, NULL, NULL))
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle->offset += count;
+
+ g_vfs_job_read_set_size (G_VFS_JOB_READ (job), count);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_READ);
+ put_data_buffer (command, handle->raw_handle);
+ g_data_output_stream_put_uint64 (command, handle->offset, NULL, NULL);
+ g_data_output_stream_put_uint32 (command, bytes_requested, NULL, NULL);
+
+ queue_command_stream_and_free (op_backend, command, read_reply, G_VFS_JOB (job), handle);
+
+ return TRUE;
+}
+
+static void
+seek_read_fstat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+ GFileInfo *info;
+ goffset file_size;
+ GVfsJobSeekRead *op_job;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ reply, NULL);
+ file_size = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ op_job = G_VFS_JOB_SEEK_READ (job);
+
+ switch (op_job->seek_type)
+ {
+ case G_SEEK_CUR:
+ handle->offset += op_job->requested_offset;
+ break;
+ case G_SEEK_SET:
+ handle->offset = op_job->requested_offset;
+ break;
+ case G_SEEK_END:
+ handle->offset = file_size + op_job->requested_offset;
+ break;
+ }
+
+ if (handle->offset < 0)
+ handle->offset = 0;
+ if (handle->offset > file_size)
+ handle->offset = file_size;
+
+ g_vfs_job_seek_read_set_offset (op_job, handle->offset);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_FSTAT);
+ put_data_buffer (command, handle->raw_handle);
+
+ queue_command_stream_and_free (op_backend, command, seek_read_fstat_reply, G_VFS_JOB (job), handle);
+
+ return TRUE;
+}
+
+static void
+delete_temp_file (GVfsBackendSftp *backend,
+ SftpHandle *handle,
+ GVfsJob *job)
+{
+ GDataOutputStream *command;
+
+ if (handle->tempname)
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ put_string (command, handle->tempname);
+ queue_command_stream_and_free (backend, command, NULL, job, NULL);
+ }
+}
+
+static void
+close_moved_tempfile (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+
+ /* On failure, don't remove tempfile, since we removed the new original file */
+ sftp_handle_free (handle);
+}
+
+static void
+close_restore_permissions (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GDataOutputStream *command;
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ /* Here we don't really care whether or not setting the permissions succeeded
+ or not. We just take the last step and rename the temp file to the
+ actual file */
+ command = new_command_stream (backend,
+ SSH_FXP_RENAME);
+ put_string (command, handle->tempname);
+ put_string (command, handle->filename);
+ queue_command_stream_and_free (backend, command, close_moved_tempfile, G_VFS_JOB (job), handle);
+}
+
+static void
+close_deleted_file (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GDataOutputStream *command;
+ GError *error;
+ gboolean res;
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ error = NULL;
+ res = FALSE;
+ if (reply_type == SSH_FXP_STATUS)
+ res = error_from_status (job, reply, -1, -1, &error);
+ else
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+
+ if (res)
+ {
+ /* Removed original file, now first try to restore permissions */
+ command = new_command_stream (backend,
+ SSH_FXP_SETSTAT);
+ put_string (command, handle->tempname);
+ g_data_output_stream_put_uint32 (command, SSH_FILEXFER_ATTR_PERMISSIONS, NULL, NULL);
+ g_data_output_stream_put_uint32 (command, handle->permissions, NULL, NULL);
+ queue_command_stream_and_free (backend, command, close_restore_permissions, G_VFS_JOB (job), handle);
+ }
+ else
+ {
+ /* The delete failed, remove any temporary files */
+ delete_temp_file (backend,
+ handle,
+ G_VFS_JOB (job));
+
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ sftp_handle_free (handle);
+ }
+}
+
+static void
+close_moved_file (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GDataOutputStream *command;
+ GError *error;
+ gboolean res;
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ error = NULL;
+ res = FALSE;
+ if (reply_type == SSH_FXP_STATUS)
+ res = error_from_status (job, reply, -1, -1, &error);
+ else
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+
+ if (res)
+ {
+ /* moved original file to backup, now move new file in place */
+
+ command = new_command_stream (backend,
+ SSH_FXP_RENAME);
+ put_string (command, handle->tempname);
+ put_string (command, handle->filename);
+ queue_command_stream_and_free (backend, command, close_moved_tempfile, G_VFS_JOB (job), handle);
+ }
+ else
+ {
+ /* Move original file to backup name failed, remove any temporary files */
+ delete_temp_file (backend,
+ handle,
+ G_VFS_JOB (job));
+
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("Error creating backup file: %s"), error->message);
+ g_error_free (error);
+ sftp_handle_free (handle);
+ }
+}
+
+static void
+close_deleted_backup (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+ GDataOutputStream *command;
+ char *backup_name;
+
+ /* Ignore result here, if it failed we'll just get a new error when moving over it
+ * This is simpler than ignoring NOEXIST errors
+ */
+
+ handle = user_data;
+
+ command = new_command_stream (backend,
+ SSH_FXP_RENAME);
+ backup_name = g_strconcat (handle->filename, "~", NULL);
+ put_string (command, handle->filename);
+ put_string (command, backup_name);
+ g_free (backup_name);
+ queue_command_stream_and_free (backend, command, close_moved_file, G_VFS_JOB (job), handle);
+}
+
+static void
+close_write_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GDataOutputStream *command;
+ GError *error;
+ gboolean res;
+ char *backup_name;
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ error = NULL;
+ res = FALSE;
+ if (reply_type == SSH_FXP_STATUS)
+ res = error_from_status (job, reply, -1, -1, &error);
+ else
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+
+ if (res)
+ {
+ if (handle->tempname)
+ {
+ if (handle->make_backup)
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ backup_name = g_strconcat (handle->filename, "~", NULL);
+ put_string (command, backup_name);
+ g_free (backup_name);
+ queue_command_stream_and_free (backend, command, close_deleted_backup, G_VFS_JOB (job), handle);
+ }
+ else
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ put_string (command, handle->filename);
+ queue_command_stream_and_free (backend, command, close_deleted_file, G_VFS_JOB (job), handle);
+ }
+ }
+ else
+ {
+ g_vfs_job_succeeded (job);
+ sftp_handle_free (handle);
+ }
+ }
+ else
+ {
+ /* The close failed, remove any temporary files */
+ delete_temp_file (backend,
+ handle,
+ G_VFS_JOB (job));
+
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+
+ sftp_handle_free (handle);
+ }
+}
+
+static void
+close_write_fstat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle = user_data;
+ GDataOutputStream *command;
+ GFileInfo *info;
+ const char *etag;
+
+ if (reply_type == SSH_FXP_ATTRS)
+ {
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ reply, NULL);
+ etag = g_file_info_get_etag (info);
+ if (etag)
+ g_vfs_job_close_write_set_etag (G_VFS_JOB_CLOSE_WRITE (job), etag);
+ g_object_unref (info);
+ }
+
+ command = new_command_stream (backend, SSH_FXP_CLOSE);
+ put_data_buffer (command, handle->raw_handle);
+
+ queue_command_stream_and_free (backend, command, close_write_reply, G_VFS_JOB (job), handle);
+}
+
+static gboolean
+try_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle _handle)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend, SSH_FXP_FSTAT);
+ put_data_buffer (command, handle->raw_handle);
+
+ queue_command_stream_and_free (op_backend, command, close_write_fstat_reply, G_VFS_JOB (job), handle);
+
+ return TRUE;
+}
+
+
+static void
+close_read_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ sftp_handle_free (handle);
+}
+
+static gboolean
+try_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle _handle)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend, SSH_FXP_CLOSE);
+ put_data_buffer (command, handle->raw_handle);
+
+ queue_command_stream_and_free (op_backend, command, close_read_reply, G_VFS_JOB (job), handle);
+
+ return TRUE;
+}
+
+static void
+create_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, G_IO_ERROR_EXISTS, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), handle);
+ g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), TRUE);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPEN);
+ put_string (command, filename);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_EXCL, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL); /* Attr flags */
+
+ queue_command_stream_and_free (op_backend, command, create_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+append_to_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), handle);
+ g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), FALSE);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPEN);
+ put_string (command, filename);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_APPEND, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL); /* Attr flags */
+
+ queue_command_stream_and_free (op_backend, command, append_to_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+typedef struct {
+ guint32 permissions;
+ guint32 uid;
+ guint32 gid;
+ gboolean set_ownership;
+ char *tempname;
+ int temp_count;
+} ReplaceData;
+
+static void
+replace_data_free (ReplaceData *data)
+{
+ g_free (data->tempname);
+ g_slice_free (ReplaceData, data);
+}
+
+static void replace_create_temp (GVfsBackendSftp *backend,
+ GVfsJobOpenForWrite *job);
+
+static void
+replace_truncate_original_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobOpenForWrite *op_job;
+ SftpHandle *handle;
+ ReplaceData *data;
+ GError *error = NULL;
+
+ op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ data = G_VFS_JOB (job)->backend_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ error = NULL;
+ if (error_from_status (job, reply, G_IO_ERROR_EXISTS, -1, &error))
+ /* Open should not return OK */
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ else
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ }
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+ handle->filename = g_strdup (op_job->filename);
+ handle->tempname = NULL;
+ handle->permissions = data->permissions;
+ handle->make_backup = op_job->make_backup;
+
+ g_vfs_job_open_for_write_set_handle (op_job, handle);
+ g_vfs_job_open_for_write_set_can_seek (op_job, TRUE);
+
+ g_vfs_job_succeeded (job);
+}
+
+static void
+replace_truncate_original (GVfsBackendSftp *backend,
+ GVfsJob *job)
+{
+ GVfsJobOpenForWrite *op_job;
+ GDataOutputStream *command;
+ ReplaceData *data;
+
+ data = job->backend_data;
+ op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+
+ command = new_command_stream (backend,
+ SSH_FXP_OPEN);
+ put_string (command, op_job->filename);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL); /* Attr flags */
+
+ queue_command_stream_and_free (backend, command, replace_truncate_original_reply, job, NULL);
+}
+
+static void
+replace_create_temp_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobOpenForWrite *op_job;
+ SftpHandle *handle;
+ ReplaceData *data;
+ GError *error;
+
+ op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ data = G_VFS_JOB (job)->backend_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ error = NULL;
+ if (error_from_status (job, reply, G_IO_ERROR_EXISTS, -1, &error))
+ /* Open should not return OK */
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ else if (error->code == G_IO_ERROR_EXISTS)
+ {
+ /* It was *probably* the EXCL flag failing. I wish we had
+ an actual real error code for that, grumble */
+ g_error_free (error);
+
+ replace_create_temp (backend, op_job);
+ }
+ else if (data->set_ownership &&
+ error->code == G_IO_ERROR_PERMISSION_DENIED)
+ {
+ g_error_free (error);
+
+ /* This was probably due to the fact that the ownership could not be
+ set properly. In this case we change our strategy altogether and
+ simply open/truncate the original file. This is not as secure
+ as the atomit tempfile/move approach, but at least ownership
+ doesn't change */
+ if (!op_job->make_backup)
+ replace_truncate_original (backend, job);
+ else
+ {
+ /* We only do this if make_backup is FALSE, as this version breaks
+ the backup code. Would like to handle the backup case too by
+ backing up before truncating, but for now error out... */
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("backups not supported yet"));
+ }
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ }
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+ handle->filename = g_strdup (op_job->filename);
+ handle->tempname = g_strdup (data->tempname);
+ handle->permissions = data->permissions;
+ handle->make_backup = op_job->make_backup;
+
+ g_vfs_job_open_for_write_set_handle (op_job, handle);
+ g_vfs_job_open_for_write_set_can_seek (op_job, TRUE);
+
+ g_vfs_job_succeeded (job);
+}
+
+static void
+random_text (char *s)
+{
+ static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ static const int NLETTERS = sizeof (letters) - 1;
+ static int counter = 0;
+
+ GTimeVal tv;
+ glong value;
+
+ /* Get some more or less random data. */
+ g_get_current_time (&tv);
+ value = (tv.tv_usec ^ tv.tv_sec) + counter++;
+
+ /* Fill in the random bits. */
+ s[0] = letters[value % NLETTERS];
+ value /= NLETTERS;
+ s[1] = letters[value % NLETTERS];
+ value /= NLETTERS;
+ s[2] = letters[value % NLETTERS];
+ value /= NLETTERS;
+ s[3] = letters[value % NLETTERS];
+ value /= NLETTERS;
+ s[4] = letters[value % NLETTERS];
+ value /= NLETTERS;
+ s[5] = letters[value % NLETTERS];
+}
+
+static void
+replace_create_temp (GVfsBackendSftp *backend,
+ GVfsJobOpenForWrite *job)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ char *dirname;
+ ReplaceData *data;
+ char basename[] = ".giosaveXXXXXX";
+
+ data = G_VFS_JOB (job)->backend_data;
+
+ data->temp_count++;
+
+ if (data->temp_count == 100)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Unable to create temporary file"));
+ return;
+ }
+
+ g_free (data->tempname);
+
+ dirname = g_path_get_dirname (job->filename);
+ random_text (basename + 8);
+ data->tempname = g_build_filename (dirname, basename, NULL);
+ g_free (dirname);
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPEN);
+ put_string (command, data->tempname);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_EXCL, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, SSH_FILEXFER_ATTR_PERMISSIONS | (data->set_ownership ? SSH_FILEXFER_ATTR_UIDGID : 0), NULL, NULL); /* Attr flags */
+
+ if (data->set_ownership)
+ {
+ g_data_output_stream_put_uint32 (command, data->uid, NULL, NULL);
+ g_data_output_stream_put_uint32 (command, data->gid, NULL, NULL);
+ }
+
+ g_data_output_stream_put_uint32 (command, data->permissions, NULL, NULL);
+ queue_command_stream_and_free (op_backend, command, replace_create_temp_reply, G_VFS_JOB (job), NULL);
+}
+
+static void
+replace_stat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GFileInfo *info;
+ GVfsJobOpenForWrite *op_job;
+ const char *current_etag;
+ guint32 permissions;
+ guint32 uid;
+ guint32 gid;
+ gboolean set_ownership = FALSE;
+ ReplaceData *data;
+
+ op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+
+ permissions = 0644;
+
+ if (reply_type == SSH_FXP_ATTRS)
+ {
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ reply, NULL);
+
+ if (op_job->etag != NULL)
+ {
+ current_etag = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE);
+
+ if (current_etag == NULL ||
+ strcmp (op_job->etag, current_etag) != 0)
+ {
+ g_vfs_job_failed (job,
+ G_IO_ERROR, G_IO_ERROR_WRONG_ETAG,
+ _("The file was externally modified"));
+ g_object_unref (info);
+ return;
+ }
+ }
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE))
+ permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & 0777;
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID) && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID))
+ {
+ set_ownership = TRUE;
+ uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID);
+ gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID);
+ }
+ }
+
+ data = g_slice_new0 (ReplaceData);
+ data->permissions = permissions;
+ data->set_ownership = set_ownership;
+
+ if (set_ownership)
+ {
+ data->uid = uid;
+ data->gid = gid;
+ }
+
+ g_vfs_job_set_backend_data (job, data, (GDestroyNotify)replace_data_free);
+
+ replace_create_temp (backend, op_job);
+}
+
+static void
+replace_exclusive_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobOpenForWrite *op_job;
+ GDataOutputStream *command;
+ SftpHandle *handle;
+ GError *error;
+
+ op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ error = NULL;
+ if (error_from_status (job, reply, G_IO_ERROR_EXISTS, -1, &error))
+ /* Open should not return OK */
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ else if (error->code == G_IO_ERROR_EXISTS)
+ {
+ /* It was *probably* the EXCL flag failing. I wish we had
+ an actual real error code for that, grumble */
+ g_error_free (error);
+
+ /* Replace existing file code: */
+
+ command = new_command_stream (backend,
+ SSH_FXP_STAT);
+ put_string (command, op_job->filename);
+ queue_command_stream_and_free (backend, command, replace_stat_reply, G_VFS_JOB (job), NULL);
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ }
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ handle = sftp_handle_new (reply);
+
+ g_vfs_job_open_for_write_set_handle (op_job, handle);
+ g_vfs_job_open_for_write_set_can_seek (op_job, TRUE);
+
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPEN);
+ put_string (command, filename);
+ g_data_output_stream_put_uint32 (command, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_EXCL, NULL, NULL); /* open flags */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL); /* Attr flags */
+
+ queue_command_stream_and_free (op_backend, command, replace_exclusive_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+write_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ if (result_from_status (job, reply, -1, -1))
+ {
+ handle->offset += G_VFS_JOB_WRITE (job)->data_size;
+ }
+ }
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static gboolean
+try_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_WRITE);
+ put_data_buffer (command, handle->raw_handle);
+ g_data_output_stream_put_uint64 (command, handle->offset, NULL, NULL);
+ g_data_output_stream_put_uint32 (command, buffer_size, NULL, NULL);
+ /* Ideally we shouldn't do this copy, but doing the writes as multiple writes
+ caused problems on the read side in openssh */
+ g_output_stream_write_all (G_OUTPUT_STREAM (command),
+ buffer, buffer_size,
+ NULL, NULL, NULL);
+
+ queue_command_stream_and_free (op_backend, command, write_reply, G_VFS_JOB (job), handle);
+
+ /* We always write the full size (on success) */
+ g_vfs_job_write_set_written_size (job, buffer_size);
+
+ return TRUE;
+}
+
+static void
+seek_write_fstat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ SftpHandle *handle;
+ GFileInfo *info;
+ goffset file_size;
+ GVfsJobSeekWrite *op_job;
+
+ handle = user_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ reply, NULL);
+ file_size = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ op_job = G_VFS_JOB_SEEK_WRITE (job);
+
+ switch (op_job->seek_type)
+ {
+ case G_SEEK_CUR:
+ handle->offset += op_job->requested_offset;
+ break;
+ case G_SEEK_SET:
+ handle->offset = op_job->requested_offset;
+ break;
+ case G_SEEK_END:
+ handle->offset = file_size + op_job->requested_offset;
+ break;
+ }
+
+ if (handle->offset < 0)
+ handle->offset = 0;
+ if (handle->offset > file_size)
+ handle->offset = file_size;
+
+ g_vfs_job_seek_write_set_offset (op_job, handle->offset);
+ g_vfs_job_succeeded (job);
+}
+
+static gboolean
+try_seek_on_write (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_FSTAT);
+ put_data_buffer (command, handle->raw_handle);
+
+ queue_command_stream_and_free (op_backend, command, seek_write_fstat_reply, G_VFS_JOB (job), handle);
+
+ return TRUE;
+}
+
+typedef struct {
+ DataBuffer *handle;
+ int outstanding_requests;
+} ReadDirData;
+
+static
+void
+read_dir_data_free (ReadDirData *data)
+{
+ data_buffer_free (data->handle);
+ g_slice_free (ReadDirData, data);
+}
+
+static void
+read_dir_readlink_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ ReadDirData *data;
+ GFileInfo *info = user_data;
+ char *target;
+
+ data = job->backend_data;
+
+ if (reply_type == SSH_FXP_NAME)
+ {
+ /* count = */ (void) g_data_input_stream_read_uint32 (reply, NULL, NULL);
+
+ target = read_string (reply, NULL);
+ if (target)
+ {
+ g_file_info_set_symlink_target (info, target);
+ g_free (target);
+ }
+ }
+
+ g_vfs_job_enumerate_add_info (G_VFS_JOB_ENUMERATE (job), info);
+ g_object_unref (info);
+
+ if (--data->outstanding_requests == 0)
+ g_vfs_job_enumerate_done (G_VFS_JOB_ENUMERATE (job));
+}
+
+static void
+read_dir_got_stat_info (GVfsBackendSftp *backend,
+ GVfsJob *job,
+ GFileInfo *info)
+{
+ GVfsJobEnumerate *enum_job;
+ GDataOutputStream *command;
+ ReadDirData *data;
+ char *abs_name;
+
+ data = job->backend_data;
+
+ enum_job = G_VFS_JOB_ENUMERATE (job);
+
+ if (g_file_attribute_matcher_matches (enum_job->attribute_matcher,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
+ {
+ data->outstanding_requests++;
+ command = new_command_stream (backend,
+ SSH_FXP_READLINK);
+ abs_name = g_build_filename (enum_job->filename, g_file_info_get_name (info), NULL);
+ put_string (command, abs_name);
+ g_free (abs_name);
+ queue_command_stream_and_free (backend, command, read_dir_readlink_reply, G_VFS_JOB (job), g_object_ref (info));
+ }
+ else
+ g_vfs_job_enumerate_add_info (enum_job, info);
+}
+
+
+static void
+read_dir_symlink_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ const char *name;
+ GFileInfo *info;
+ GFileInfo *lstat_info;
+ ReadDirData *data;
+
+ lstat_info = user_data;
+ name = g_file_info_get_name (lstat_info);
+ data = job->backend_data;
+
+ if (reply_type == SSH_FXP_ATTRS)
+ {
+ info = g_file_info_new ();
+ g_file_info_set_name (info, name);
+ g_file_info_set_is_symlink (info, TRUE);
+
+ parse_attributes (backend, info, name, reply, G_VFS_JOB_ENUMERATE (job)->attribute_matcher);
+
+ read_dir_got_stat_info (backend, job, info);
+
+ g_object_unref (info);
+ }
+ else
+ read_dir_got_stat_info (backend, job, lstat_info);
+
+ g_object_unref (lstat_info);
+
+ if (--data->outstanding_requests == 0)
+ g_vfs_job_enumerate_done (G_VFS_JOB_ENUMERATE (job));
+}
+
+static void
+read_dir_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobEnumerate *enum_job;
+ guint32 count;
+ int i;
+ GDataOutputStream *command;
+ ReadDirData *data;
+
+ data = job->backend_data;
+ enum_job = G_VFS_JOB_ENUMERATE (job);
+
+ if (reply_type != SSH_FXP_NAME)
+ {
+ /* Ignore all error, including the expected END OF FILE.
+ * Real errors are expected in open_dir anyway */
+
+ /* Close handle */
+
+ command = new_command_stream (backend,
+ SSH_FXP_CLOSE);
+ put_data_buffer (command, data->handle);
+ queue_command_stream_and_free (backend, command, NULL, G_VFS_JOB (job), NULL);
+
+ if (--data->outstanding_requests == 0)
+ g_vfs_job_enumerate_done (enum_job);
+
+ return;
+ }
+
+ count = g_data_input_stream_read_uint32 (reply, NULL, NULL);
+ for (i = 0; i < count; i++)
+ {
+ GFileInfo *info;
+ char *name;
+ char *longname;
+ char *abs_name;
+
+ info = g_file_info_new ();
+ name = read_string (reply, NULL);
+ g_file_info_set_name (info, name);
+
+ longname = read_string (reply, NULL);
+ g_free (longname);
+
+ parse_attributes (backend, info, name, reply, enum_job->attribute_matcher);
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK &&
+ ! (enum_job->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
+ {
+ /* Default (at least for openssh) is for readdir to not follow symlinks.
+ This was a symlink, and follow links was requested, so we need to manually follow it */
+ command = new_command_stream (backend,
+ SSH_FXP_STAT);
+ abs_name = g_build_filename (enum_job->filename, name, NULL);
+ put_string (command, abs_name);
+ g_free (abs_name);
+
+ queue_command_stream_and_free (backend, command, read_dir_symlink_reply, G_VFS_JOB (job), g_object_ref (info));
+ data->outstanding_requests ++;
+ }
+ else if (strcmp (".", name) != 0 &&
+ strcmp ("..", name) != 0)
+ read_dir_got_stat_info (backend, job, info);
+
+ g_object_unref (info);
+ g_free (name);
+ }
+
+ command = new_command_stream (backend,
+ SSH_FXP_READDIR);
+ put_data_buffer (command, data->handle);
+ queue_command_stream_and_free (backend, command, read_dir_reply, G_VFS_JOB (job), NULL);
+}
+
+static void
+open_dir_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ ReadDirData *data;
+
+ data = job->backend_data;
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_HANDLE)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ data->handle = read_data_buffer (reply);
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_READDIR);
+ put_data_buffer (command, data->handle);
+
+ data->outstanding_requests = 1;
+
+ queue_command_stream_and_free (op_backend, command, read_dir_reply, G_VFS_JOB (job), NULL);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ ReadDirData *data;
+
+ data = g_slice_new0 (ReadDirData);
+
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), data, (GDestroyNotify)read_dir_data_free);
+ command = new_command_stream (op_backend,
+ SSH_FXP_OPENDIR);
+ put_string (command, filename);
+
+ queue_command_stream_and_free (op_backend, command, open_dir_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+query_info_reply (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ char *basename;
+ int i;
+ MultiReply *lstat_reply, *reply;
+ GFileInfo *lstat_info;
+ GVfsJobQueryInfo *op_job;
+
+ op_job = G_VFS_JOB_QUERY_INFO (job);
+
+ i = 0;
+ lstat_reply = &replies[i++];
+
+ if (lstat_reply->type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, lstat_reply->data, -1, -1);
+ return;
+ }
+ else if (lstat_reply->type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid reply received"));
+ return;
+ }
+
+ basename = NULL;
+ if (strcmp (op_job->filename, "/") != 0)
+ basename = g_path_get_basename (op_job->filename);
+
+ if (op_job->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
+ {
+ parse_attributes (backend, op_job->file_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
+ }
+ else
+ {
+ /* Look at stat results */
+ reply = &replies[i++];
+
+ if (reply->type == SSH_FXP_ATTRS)
+ {
+ parse_attributes (backend, op_job->file_info, basename,
+ reply->data, op_job->attribute_matcher);
+
+
+ lstat_info = g_file_info_new ();
+ parse_attributes (backend, lstat_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
+ if (g_file_info_get_is_symlink (lstat_info))
+ g_file_info_set_is_symlink (op_job->file_info, TRUE);
+ g_object_unref (lstat_info);
+ }
+ else
+ {
+ /* Broken symlink, use lstat data */
+ parse_attributes (backend, op_job->file_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
+ }
+
+ }
+
+ g_free (basename);
+
+ if (g_file_attribute_matcher_matches (op_job->attribute_matcher,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
+ {
+ /* Look at readlink results */
+ reply = &replies[i++];
+
+ if (reply->type == SSH_FXP_NAME)
+ {
+ char *symlink_target;
+ guint32 count;
+
+ count = g_data_input_stream_read_uint32 (reply->data, NULL, NULL);
+ symlink_target = read_string (reply->data, NULL);
+ g_file_info_set_symlink_target (op_job->file_info, symlink_target);
+ g_free (symlink_target);
+ }
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *commands[3];
+ GDataOutputStream *command;
+ int n_commands;
+
+ n_commands = 0;
+
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
+ put_string (command, filename);
+
+ if (! (job->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
+ {
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_STAT);
+ put_string (command, filename);
+ }
+
+ if (g_file_attribute_matcher_matches (job->attribute_matcher,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
+ {
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_READLINK);
+ put_string (command, filename);
+ }
+
+ queue_command_streams_and_free (op_backend, commands, n_commands, query_info_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+typedef struct {
+ GFileInfo *info;
+ GFileAttributeMatcher *attribute_matcher;
+} QueryInfoFStatData;
+
+static void
+query_info_fstat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ QueryInfoFStatData *data = user_data;
+ GFileInfo *file_info;
+ GFileAttributeMatcher *attribute_matcher;
+
+ file_info = data->info;
+ attribute_matcher = data->attribute_matcher;
+ g_slice_free (QueryInfoFStatData, data);
+
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, reply, -1, -1);
+ return;
+ }
+
+ if (reply_type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ return;
+ }
+
+ parse_attributes (backend,
+ file_info,
+ NULL,
+ reply,
+ attribute_matcher);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_query_info_fstat (GVfsBackend *backend,
+ GVfsJob *job,
+ GVfsBackendHandle _handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ SftpHandle *handle = _handle;
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ QueryInfoFStatData *data;
+
+ command = new_command_stream (op_backend, SSH_FXP_FSTAT);
+ put_data_buffer (command, handle->raw_handle);
+
+ data = g_slice_new (QueryInfoFStatData);
+ data->info = info;
+ data->attribute_matcher = attribute_matcher;
+ queue_command_stream_and_free (op_backend, command, query_info_fstat_reply, G_VFS_JOB (job), data);
+
+ return TRUE;
+}
+
+static void
+move_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ goffset *file_size;
+
+ /* on any unknown error, return NOT_SUPPORTED to get the fallback implementation */
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ if (failure_from_status (job, reply, G_IO_ERROR_NOT_SUPPORTED, -1))
+ {
+ /* Succeeded, report file size */
+ file_size = job->backend_data;
+ if (file_size != NULL)
+ g_vfs_job_move_progress_callback (*file_size, *file_size, job);
+ g_vfs_job_succeeded (job);
+ }
+ }
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static void
+move_do_rename (GVfsBackendSftp *backend,
+ GVfsJob *job)
+{
+ GVfsJobMove *op_job;
+ GDataOutputStream *command;
+
+ op_job = G_VFS_JOB_MOVE (job);
+
+ command = new_command_stream (backend,
+ SSH_FXP_RENAME);
+ put_string (command, op_job->source);
+ put_string (command, op_job->destination);
+
+ queue_command_stream_and_free (backend, command, move_reply, G_VFS_JOB (job), NULL);
+}
+
+static void
+move_delete_target_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ if (failure_from_status (job, reply, -1, -1))
+ move_do_rename (backend, job);
+ }
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+
+static void
+move_lstat_reply (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobMove *op_job;
+ gboolean destination_exist, source_is_dir, dest_is_dir;
+ GDataOutputStream *command;
+ GFileInfo *info;
+ goffset *file_size;
+
+ op_job = G_VFS_JOB_MOVE (job);
+
+ if (replies[0].type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, replies[0].data, -1, -1);
+ return;
+ }
+ else if (replies[0].type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid reply received"));
+ return;
+ }
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ replies[0].data, NULL);
+ source_is_dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ file_size = g_new (goffset, 1);
+ *file_size = g_file_info_get_size (info);
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), file_size, g_free);
+ g_object_unref (info);
+
+ destination_exist = FALSE;
+ if (replies[1].type == SSH_FXP_ATTRS)
+ {
+ destination_exist = TRUE; /* Target file exists */
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ replies[1].data, NULL);
+ dest_is_dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ g_object_unref (info);
+
+ if (op_job->flags & G_FILE_COPY_OVERWRITE)
+ {
+
+ /* Always fail on dirs, even with overwrite */
+ if (dest_is_dir)
+ {
+ if (source_is_dir)
+ g_vfs_job_failed (job,
+ G_IO_ERROR,
+ G_IO_ERROR_WOULD_MERGE,
+ _("Can't move directory over directory"));
+ else
+ g_vfs_job_failed (job,
+ G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("File is directory"));
+ return;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ return;
+ }
+ }
+
+ /* TODO: Check flags & G_FILE_COPY_BACKUP */
+
+ if (destination_exist && (op_job->flags & G_FILE_COPY_OVERWRITE))
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ put_string (command, op_job->destination);
+ queue_command_stream_and_free (backend, command, move_delete_target_reply, G_VFS_JOB (job), NULL);
+ return;
+ }
+
+ move_do_rename (backend, job);
+}
+
+
+static gboolean
+try_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ GDataOutputStream *commands[2];
+
+ command = commands[0] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
+ put_string (command, source);
+
+ command = commands[1] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
+ put_string (command, destination);
+
+ queue_command_streams_and_free (op_backend, commands, 2, move_lstat_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+set_display_name_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static gboolean
+try_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+ char *dirname, *basename, *new_name;
+
+ /* We use the same setting as for local files. Can't really
+ * do better, since there is no way in this version of sftp to find out
+ * the remote charset encoding
+ */
+
+ dirname = g_path_get_dirname (filename);
+ basename = g_filename_from_utf8 (display_name, -1, NULL, NULL, NULL);
+ if (basename == NULL)
+ basename = g_strdup (display_name);
+ new_name = g_build_filename (dirname, basename, NULL);
+ g_free (dirname);
+ g_free (basename);
+
+ g_vfs_job_set_display_name_set_new_path (job,
+ new_name);
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_RENAME);
+ put_string (command, filename);
+ put_string (command, new_name);
+
+ queue_command_stream_and_free (op_backend, command, set_display_name_reply, G_VFS_JOB (job), NULL);
+
+ g_free (new_name);
+
+ return TRUE;
+}
+
+
+static void
+make_symlink_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static gboolean
+try_make_symlink (GVfsBackend *backend,
+ GVfsJobMakeSymlink *job,
+ const char *filename,
+ const char *symlink_value)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_SYMLINK);
+ /* Note: This is the reverse order of how this is documented in
+ draft-ietf-secsh-filexfer-02.txt, but its how openssh does it. */
+ put_string (command, symlink_value);
+ put_string (command, filename);
+
+ queue_command_stream_and_free (op_backend, command, make_symlink_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+make_directory_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static gboolean
+try_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_MKDIR);
+ put_string (command, filename);
+ /* No file info - flag 0 */
+ g_data_output_stream_put_uint32 (command, 0, NULL, NULL);
+
+ queue_command_stream_and_free (op_backend, command, make_directory_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+delete_remove_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static void
+delete_rmdir_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, G_IO_ERROR_NOT_EMPTY, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static void
+delete_lstat_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else if (reply_type != SSH_FXP_ATTRS)
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+ else
+ {
+ GFileInfo *info;
+ GDataOutputStream *command;
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL, reply, NULL);
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_RMDIR);
+ put_string (command, G_VFS_JOB_DELETE (job)->filename);
+ queue_command_stream_and_free (backend, command, delete_rmdir_reply, G_VFS_JOB (job), NULL);
+ }
+ else
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ put_string (command, G_VFS_JOB_DELETE (job)->filename);
+ queue_command_stream_and_free (backend, command, delete_remove_reply, G_VFS_JOB (job), NULL);
+ }
+
+ g_object_unref (info);
+ }
+}
+
+static gboolean
+try_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
+ put_string (command, filename);
+ queue_command_stream_and_free (op_backend, command, delete_lstat_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+try_query_settable_attributes (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename)
+{
+ GFileAttributeInfoList *list;
+
+ list = g_file_attribute_info_list_new ();
+
+ g_file_attribute_info_list_add (list,
+ G_FILE_ATTRIBUTE_UNIX_MODE,
+ G_FILE_ATTRIBUTE_TYPE_UINT32,
+ G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+
+ g_vfs_job_query_attributes_set_list (job, list);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_file_attribute_info_list_unref (list);
+
+ return TRUE;
+}
+
+static void
+set_attribute_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ result_from_status (job, reply, -1, -1);
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static gboolean
+try_set_attribute (GVfsBackend *backend,
+ GVfsJobSetAttribute *job,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *command;
+
+ if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) != 0)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation unsupported"));
+ return TRUE;
+ }
+
+ command = new_command_stream (op_backend,
+ SSH_FXP_SETSTAT);
+ put_string (command, filename);
+ g_data_output_stream_put_uint32 (command, SSH_FILEXFER_ATTR_PERMISSIONS, NULL, NULL);
+ g_data_output_stream_put_uint32 (command, (*(guint32 *)value_p) & 0777, NULL, NULL);
+ queue_command_stream_and_free (op_backend, command, set_attribute_reply, G_VFS_JOB (job), NULL);
+
+ return TRUE;
+}
+
+static void
+setup_icon_reply (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GIcon *icon;
+ gboolean have_favicon;
+ MultiReply *stat_reply;
+
+ have_favicon = FALSE;
+
+ stat_reply = &replies[0];
+ if (stat_reply->type == SSH_FXP_ATTRS)
+ have_favicon = TRUE;
+
+ if (have_favicon)
+ {
+ icon = g_vfs_icon_new (g_vfs_backend_get_mount_spec (G_VFS_BACKEND (backend)),
+ "favicon:/etc/favicon.png");
+ g_vfs_backend_set_icon (G_VFS_BACKEND (backend), icon);
+ g_object_unref (icon);
+ }
+ else
+ {
+ g_vfs_backend_set_icon_name (G_VFS_BACKEND (backend), "folder-remote");
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+/* called from do_mount(); finds out if there's an /etc/favicon.png file; if so, use it as the icon */
+static void
+setup_icon (GVfsBackendSftp *op_backend,
+ GVfsJobMount *job)
+{
+ GDataOutputStream *command;
+
+ command = new_command_stream (op_backend, SSH_FXP_STAT);
+ put_string (command, "/etc/favicon.png");
+
+ queue_command_streams_and_free (op_backend,
+ &command,
+ 1,
+ setup_icon_reply,
+ G_VFS_JOB (job),
+ NULL);
+}
+
+static void
+g_vfs_backend_sftp_class_init (GVfsBackendSftpClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ id_q = g_quark_from_static_string ("command-id");
+
+ gobject_class->finalize = g_vfs_backend_sftp_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->try_mount = try_mount;
+ backend_class->try_open_icon_for_read = try_open_icon_for_read;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_read = try_read;
+ backend_class->try_seek_on_read = try_seek_on_read;
+ backend_class->try_close_read = try_close_read;
+ backend_class->try_close_write = try_close_write;
+ backend_class->try_query_info = try_query_info;
+ backend_class->try_query_info_on_read = (gpointer) try_query_info_fstat;
+ backend_class->try_query_info_on_write = (gpointer) try_query_info_fstat;
+ backend_class->try_enumerate = try_enumerate;
+ backend_class->try_create = try_create;
+ backend_class->try_append_to = try_append_to;
+ backend_class->try_replace = try_replace;
+ backend_class->try_write = try_write;
+ backend_class->try_seek_on_write = try_seek_on_write;
+ backend_class->try_move = try_move;
+ backend_class->try_make_symlink = try_make_symlink;
+ backend_class->try_make_directory = try_make_directory;
+ backend_class->try_delete = try_delete;
+ backend_class->try_set_display_name = try_set_display_name;
+ backend_class->try_query_settable_attributes = try_query_settable_attributes;
+ backend_class->try_set_attribute = try_set_attribute;
+}
diff --git a/trunk/daemon/gvfsbackendsftp.h b/trunk/daemon/gvfsbackendsftp.h
new file mode 100644
index 00000000..7e40eba0
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsftp.h
@@ -0,0 +1,50 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_SFTP_H__
+#define __G_VFS_BACKEND_SFTP_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_SFTP (g_vfs_backend_sftp_get_type ())
+#define G_VFS_BACKEND_SFTP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_SFTP, GVfsBackendSftp))
+#define G_VFS_BACKEND_SFTP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_SFTP, GVfsBackendSftpClass))
+#define G_VFS_IS_BACKEND_SFTP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_SFTP))
+#define G_VFS_IS_BACKEND_SFTP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_SFTP))
+#define G_VFS_BACKEND_SFTP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_SFTP, GVfsBackendSftpClass))
+
+typedef struct _GVfsBackendSftp GVfsBackendSftp;
+typedef struct _GVfsBackendSftpClass GVfsBackendSftpClass;
+
+struct _GVfsBackendSftpClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_sftp_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_SFTP_H__ */
diff --git a/trunk/daemon/gvfsbackendsmb.c b/trunk/daemon/gvfsbackendsmb.c
new file mode 100644
index 00000000..74b8f3bd
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsmb.c
@@ -0,0 +1,2102 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gvfsbackendsmb.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsjobsetdisplayname.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryattributes.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfskeyring.h"
+
+#ifdef HAVE_GCONF
+#include <gconf/gconf-client.h>
+#endif
+
+/* We load a default workgroup from gconf */
+#define PATH_GCONF_GNOME_VFS_SMB_WORKGROUP "/system/smb/workgroup"
+
+#include <libsmbclient.h>
+#include "libsmb-compat.h"
+
+struct _GVfsBackendSmb
+{
+ GVfsBackend parent_instance;
+
+ char *server;
+ char *share;
+ char *user;
+ char *domain;
+
+ SMBCCTX *smb_context;
+
+ char *last_user;
+ char *last_domain;
+ char *last_password;
+
+ GMountSource *mount_source; /* Only used/set during mount */
+ int mount_try;
+ gboolean mount_try_again;
+ gboolean mount_cancelled;
+
+ gboolean password_in_keyring;
+ GPasswordSave password_save;
+
+ /* Cache */
+ char *cached_server_name;
+ char *cached_share_name;
+ char *cached_domain;
+ char *cached_username;
+ SMBCSRV *cached_server;
+};
+
+static char *default_workgroup = NULL;
+
+G_DEFINE_TYPE (GVfsBackendSmb, g_vfs_backend_smb, G_VFS_TYPE_BACKEND)
+
+static void set_info_from_stat (GVfsBackendSmb *backend,
+ GFileInfo *info,
+ struct stat *statbuf,
+ const char *basename,
+ GFileAttributeMatcher *matcher);
+
+
+static void
+g_vfs_backend_smb_finalize (GObject *object)
+{
+ GVfsBackendSmb *backend;
+
+ backend = G_VFS_BACKEND_SMB (object);
+
+ g_free (backend->share);
+ g_free (backend->server);
+ g_free (backend->user);
+ g_free (backend->domain);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_smb_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_smb_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_smb_init (GVfsBackendSmb *backend)
+{
+}
+
+/**
+ * Authentication callback function type (method that includes context)
+ *
+ * Type for the the authentication function called by the library to
+ * obtain authentication credentals
+ *
+ * @param context Pointer to the smb context
+ * @param srv Server being authenticated to
+ * @param shr Share being authenticated to
+ * @param wg Pointer to buffer containing a "hint" for the
+ * workgroup to be authenticated. Should be filled in
+ * with the correct workgroup if the hint is wrong.
+ * @param wglen The size of the workgroup buffer in bytes
+ * @param un Pointer to buffer containing a "hint" for the
+ * user name to be use for authentication. Should be
+ * filled in with the correct workgroup if the hint is
+ * wrong.
+ * @param unlen The size of the username buffer in bytes
+ * @param pw Pointer to buffer containing to which password
+ * copied
+ * @param pwlen The size of the password buffer in bytes
+ *
+ */
+static void
+auth_callback (SMBCCTX *context,
+ const char *server_name, const char *share_name,
+ char *domain_out, int domainmaxlen,
+ char *username_out, int unmaxlen,
+ char *password_out, int pwmaxlen)
+{
+ GVfsBackendSmb *backend;
+ char *ask_password, *ask_user, *ask_domain;
+ gboolean handled, abort;
+
+ backend = smbc_getOptionUserData (context);
+
+ strncpy (password_out, "", pwmaxlen);
+
+ if (backend->domain)
+ strncpy (domain_out, backend->domain, domainmaxlen);
+ if (backend->user)
+ strncpy (username_out, backend->user, unmaxlen);
+
+ if (backend->mount_cancelled)
+ {
+ /* Don't prompt for credentials, let smbclient finish the mount loop */
+ strncpy (username_out, "ABORT", unmaxlen);
+ strncpy (password_out, "", pwmaxlen);
+ return;
+ }
+
+ if (backend->mount_source == NULL)
+ {
+ /* Not during mount, use last password */
+ if (backend->last_user)
+ strncpy (username_out, backend->last_user, unmaxlen);
+ if (backend->last_domain)
+ strncpy (domain_out, backend->last_domain, domainmaxlen);
+ if (backend->last_password)
+ strncpy (password_out, backend->last_password, pwmaxlen);
+
+ return;
+ }
+
+ if (backend->mount_try == 0 &&
+ backend->user == NULL &&
+ backend->domain == NULL)
+ {
+ /* Try again if kerberos login + anonymous fallback fails */
+ backend->mount_try_again = TRUE;
+ }
+ else
+ {
+ gboolean in_keyring = FALSE;
+
+ if (!backend->password_in_keyring)
+ {
+ in_keyring = g_vfs_keyring_lookup_password (backend->user,
+ backend->server,
+ backend->domain,
+ "smb",
+ NULL,
+ NULL,
+ 0,
+ &ask_user,
+ &ask_domain,
+ &ask_password);
+ backend->password_in_keyring = in_keyring;
+ }
+
+ if (!in_keyring)
+ {
+ GAskPasswordFlags flags = G_ASK_PASSWORD_NEED_PASSWORD;
+ char *message;
+
+ if (g_vfs_keyring_is_available ())
+ flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+ if (backend->domain == NULL)
+ flags |= G_ASK_PASSWORD_NEED_DOMAIN;
+ if (backend->user == NULL)
+ flags |= G_ASK_PASSWORD_NEED_USERNAME;
+
+ /* translators: First %s is a share name, second is a server name */
+ message = g_strdup_printf (_("Password required for share %s on %s"),
+ share_name, server_name);
+ handled = g_mount_source_ask_password (backend->mount_source,
+ message,
+ username_out,
+ domain_out,
+ flags,
+ &abort,
+ &ask_password,
+ &ask_user,
+ &ask_domain,
+ NULL,
+ &(backend->password_save));
+ g_free (message);
+ if (!handled)
+ goto out;
+
+ if (abort)
+ {
+ strncpy (username_out, "ABORT", unmaxlen);
+ strncpy (password_out, "", pwmaxlen);
+ backend->mount_cancelled = TRUE;
+ goto out;
+ }
+ }
+
+ /* Try again if this fails */
+ backend->mount_try_again = TRUE;
+
+ strncpy (password_out, ask_password, pwmaxlen);
+ if (ask_user && *ask_user)
+ strncpy (username_out, ask_user, unmaxlen);
+ if (ask_domain && *ask_domain)
+ strncpy (domain_out, ask_domain, domainmaxlen);
+
+ out:
+ g_free (ask_password);
+ g_free (ask_user);
+ g_free (ask_domain);
+ }
+
+ backend->last_user = g_strdup (username_out);
+ backend->last_domain = g_strdup (domain_out);
+ backend->last_password = g_strdup (password_out);
+}
+
+/* Add a server to the cache system
+ *
+ * @param c pointer to smb context
+ * @param srv pointer to server to add
+ * @param server server name
+ * @param share share name
+ * @param workgroup workgroup used to connect
+ * @param username username used to connect
+ * @return 0 on success. 1 on failure.
+ *
+ */
+static int
+add_cached_server (SMBCCTX *context, SMBCSRV *new,
+ const char *server_name, const char *share_name,
+ const char *domain, const char *username)
+{
+ GVfsBackendSmb *backend;
+
+ backend = smbc_getOptionUserData (context);
+
+ if (backend->cached_server != NULL)
+ return 1;
+
+ backend->cached_server_name = g_strdup (server_name);
+ backend->cached_share_name = g_strdup (share_name);
+ backend->cached_domain = g_strdup (domain);
+ backend->cached_username = g_strdup (username);
+ backend->cached_server = new;
+
+ return 0;
+}
+
+/* Remove cached server
+ *
+ * @param c pointer to smb context
+ * @param srv pointer to server to remove
+ * @return 0 when found and removed. 1 on failure.
+ *
+ */
+static int
+remove_cached_server(SMBCCTX * context, SMBCSRV * server)
+{
+ GVfsBackendSmb *backend;
+
+ backend = smbc_getOptionUserData (context);
+
+ if (backend->cached_server == server)
+ {
+ g_free (backend->cached_server_name);
+ backend->cached_server_name = NULL;
+ g_free (backend->cached_share_name);
+ backend->cached_share_name = NULL;
+ g_free (backend->cached_domain);
+ backend->cached_domain = NULL;
+ g_free (backend->cached_username);
+ backend->cached_username = NULL;
+ backend->cached_server = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Look up a server in the cache system
+ *
+ * @param c pointer to smb context
+ * @param server server name to match
+ * @param share share name to match
+ * @param workgroup workgroup to match
+ * @param username username to match
+ * @return pointer to SMBCSRV on success. NULL on failure.
+ *
+ */
+static SMBCSRV *
+get_cached_server (SMBCCTX * context,
+ const char *server_name, const char *share_name,
+ const char *domain, const char *username)
+{
+ GVfsBackendSmb *backend;
+
+ backend = smbc_getOptionUserData (context);
+
+ if (backend->cached_server != NULL &&
+ strcmp (backend->cached_server_name, server_name) == 0 &&
+ strcmp (backend->cached_share_name, share_name) == 0 &&
+ strcmp (backend->cached_domain, domain) == 0 &&
+ strcmp (backend->cached_username, username) == 0)
+ return backend->cached_server;
+
+ return NULL;
+}
+
+/* Try to remove all servers from the cache system and disconnect
+ *
+ * @param c pointer to smb context
+ *
+ * @return 0 when found and removed. 1 on failure.
+ *
+ */
+static int
+purge_cached (SMBCCTX * context)
+{
+ GVfsBackendSmb *backend;
+
+ backend = smbc_getOptionUserData (context);
+
+ if (backend->cached_server)
+ remove_cached_server(context, backend->cached_server);
+
+ return 0;
+}
+
+#define SUB_DELIM_CHARS "!$&'()*+,;="
+
+static gboolean
+is_valid (char c, const char *reserved_chars_allowed)
+{
+ if (g_ascii_isalnum (c) ||
+ c == '-' ||
+ c == '.' ||
+ c == '_' ||
+ c == '~')
+ return TRUE;
+
+ if (reserved_chars_allowed &&
+ strchr (reserved_chars_allowed, c) != NULL)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+g_string_append_encoded (GString *string,
+ const char *encoded,
+ const char *reserved_chars_allowed)
+{
+ char c;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ while ((c = *encoded++) != 0)
+ {
+ if (is_valid (c, reserved_chars_allowed))
+ g_string_append_c (string, c);
+ else
+ {
+ g_string_append_c (string, '%');
+ g_string_append_c (string, hex[((guchar)c) >> 4]);
+ g_string_append_c (string, hex[((guchar)c) & 0xf]);
+ }
+ }
+}
+
+static GString *
+create_smb_uri_string (const char *server,
+ const char *share,
+ const char *path)
+{
+ GString *uri;
+
+ uri = g_string_new ("smb://");
+ g_string_append_encoded (uri, server, NULL);
+ g_string_append_c (uri, '/');
+ g_string_append_encoded (uri, share, NULL);
+ if (path != NULL)
+ {
+ if (*path != '/')
+ g_string_append_c (uri, '/');
+ g_string_append_encoded (uri, path, SUB_DELIM_CHARS ":@/");
+ }
+
+ while (uri->len > 0 &&
+ uri->str[uri->len - 1] == '/')
+ g_string_erase (uri, uri->len - 1, 1);
+
+ return uri;
+}
+
+static char *
+create_smb_uri (const char *server,
+ const char *share,
+ const char *path)
+{
+ GString *uri;
+ uri = create_smb_uri_string (server, share, path);
+ return g_string_free (uri, FALSE);
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ SMBCCTX *smb_context;
+ struct stat st;
+ char *uri;
+ int res;
+ char *display_name;
+ const char *debug;
+ int debug_val;
+ GMountSpec *smb_mount_spec;
+ smbc_stat_fn smbc_stat;
+
+ smb_context = smbc_new_context ();
+ if (smb_context == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Internal Error (%s)"), "Failed to allocate smb context");
+ return;
+ }
+ smbc_setOptionUserData (smb_context, backend);
+
+ debug = g_getenv ("GVFS_SMB_DEBUG");
+ if (debug)
+ debug_val = atoi (debug);
+ else
+ debug_val = 0;
+
+ smbc_setDebug (smb_context, debug_val);
+ smbc_setFunctionAuthDataWithContext (smb_context, auth_callback);
+
+ smbc_setFunctionAddCachedServer (smb_context, add_cached_server);
+ smbc_setFunctionGetCachedServer (smb_context, get_cached_server);
+ smbc_setFunctionRemoveCachedServer (smb_context, remove_cached_server);
+ smbc_setFunctionPurgeCachedServers (smb_context, purge_cached);
+
+ /* FIXME: is strdup() still needed here? -- removed */
+ if (default_workgroup != NULL)
+ smbc_setWorkgroup (smb_context, default_workgroup);
+
+#ifndef DEPRECATED_SMBC_INTERFACE
+ smb_context->flags = 0;
+#endif
+
+ /* Initial settings:
+ * - use Kerberos (always)
+ * - in case of no username specified, try anonymous login
+ */
+ smbc_setOptionUseKerberos (smb_context, 1);
+ smbc_setOptionFallbackAfterKerberos (smb_context,
+ op_backend->user != NULL);
+ smbc_setOptionNoAutoAnonymousLogin (smb_context,
+ op_backend->user != NULL);
+
+
+#if 0
+ smbc_setOptionDebugToStderr (smb_context, 1);
+#endif
+
+ if (!smbc_init_context (smb_context))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Internal Error (%s)"), "Failed to initialize smb context");
+ smbc_free_context (smb_context, FALSE);
+ return;
+ }
+
+ op_backend->smb_context = smb_context;
+
+ /* Set the mountspec according to original uri, no matter whether user changes
+ credentials during mount loop. Nautilus and other gio clients depend
+ on correct mountspec, setting it to real (different) credentials would
+ lead to G_IO_ERROR_NOT_MOUNTED errors
+ */
+
+ /* Translators: This is "<sharename> on <servername>" and is used as name for an SMB share */
+ display_name = g_strdup_printf (_("%s on %s"), op_backend->share, op_backend->server);
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+ g_vfs_backend_set_icon_name (backend, "folder-remote");
+
+ smb_mount_spec = g_mount_spec_new ("smb-share");
+ g_mount_spec_set (smb_mount_spec, "share", op_backend->share);
+ g_mount_spec_set (smb_mount_spec, "server", op_backend->server);
+ if (op_backend->user)
+ g_mount_spec_set (smb_mount_spec, "user", op_backend->user);
+ if (op_backend->domain)
+ g_mount_spec_set (smb_mount_spec, "domain", op_backend->domain);
+
+ g_vfs_backend_set_mount_spec (backend, smb_mount_spec);
+ g_mount_spec_unref (smb_mount_spec);
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, NULL);
+
+
+ /* Samba mount loop */
+ op_backend->mount_source = mount_source;
+ op_backend->mount_try = 0;
+ op_backend->password_save = G_PASSWORD_SAVE_NEVER;
+
+ do
+ {
+ op_backend->mount_try_again = FALSE;
+ op_backend->mount_cancelled = FALSE;
+
+ smbc_stat = smbc_getFunctionStat (smb_context);
+ res = smbc_stat (smb_context, uri, &st);
+
+ if (res == 0 || op_backend->mount_cancelled ||
+ (errno != EACCES && errno != EPERM))
+ break;
+
+ /* The first round is Kerberos-only. Only if this fails do we enable
+ * NTLMSSP fallback (turning off anonymous fallback, which we've
+ * already tried and failed with).
+ */
+ if (op_backend->mount_try == 0)
+ {
+ smbc_setOptionFallbackAfterKerberos (op_backend->smb_context, 1);
+ smbc_setOptionNoAutoAnonymousLogin (op_backend->smb_context, 1);
+ }
+ op_backend->mount_try ++;
+ }
+ while (op_backend->mount_try_again);
+
+ g_free (uri);
+
+ op_backend->mount_source = NULL;
+
+ if (res != 0)
+ {
+ /* TODO: Error from errno? */
+ op_backend->mount_source = NULL;
+
+ if (op_backend->mount_cancelled)
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Password dialog cancelled"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ /* translators: We tried to mount a windows (samba) share, but failed */
+ _("Failed to mount Windows share"));
+
+ return;
+ }
+
+ /* Mount was successful */
+
+ g_vfs_keyring_save_password (op_backend->last_user,
+ op_backend->server,
+ op_backend->last_domain,
+ "smb",
+ NULL,
+ NULL,
+ 0,
+ op_backend->last_password,
+ op_backend->password_save);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ const char *server, *share, *user, *domain;
+
+ server = g_mount_spec_get (mount_spec, "server");
+ share = g_mount_spec_get (mount_spec, "share");
+
+ if (server == NULL || share == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return TRUE;
+ }
+
+ user = g_mount_spec_get (mount_spec, "user");
+ domain = g_mount_spec_get (mount_spec, "domain");
+
+ op_backend->server = g_strdup (server);
+ op_backend->share = g_strdup (share);
+ op_backend->user = g_strdup (user);
+ op_backend->domain = g_strdup (domain);
+
+ return FALSE;
+}
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *uri;
+ SMBCFILE *file;
+ struct stat st;
+ smbc_open_fn smbc_open;
+ smbc_stat_fn smbc_stat;
+ int res;
+ int olderr;
+
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
+ file = smbc_open (op_backend->smb_context, uri, O_RDONLY, 0);
+
+ if (file == NULL)
+ {
+ olderr = errno;
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+ res = smbc_stat (op_backend->smb_context, uri, &st);
+ g_free (uri);
+ if ((res == 0) && (S_ISDIR (st.st_mode)))
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+ else
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), olderr);
+ }
+ else
+ {
+
+ g_vfs_job_open_for_read_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_read_set_handle (job, file);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ ssize_t res;
+ smbc_read_fn smbc_read;
+
+ /* For some reason requests of 65536 bytes broke for me (returned 0)
+ * Maybe some smb protocol limit
+ */
+ if (bytes_requested > 65535)
+ bytes_requested = 65535;
+
+ smbc_read = smbc_getFunctionRead (op_backend->smb_context);
+ res = smbc_read (op_backend->smb_context, (SMBCFILE *)handle, buffer, bytes_requested);
+
+ if (res == -1)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ g_vfs_job_read_set_size (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ }
+}
+
+static void
+do_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ int whence;
+ off_t res;
+ smbc_lseek_fn smbc_lseek;
+
+ switch (type)
+ {
+ case G_SEEK_SET:
+ whence = SEEK_SET;
+ break;
+ case G_SEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case G_SEEK_END:
+ whence = SEEK_END;
+ break;
+ default:
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Unsupported seek type"));
+ return;
+ }
+
+ smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
+ res = smbc_lseek (op_backend->smb_context, (SMBCFILE *)handle, offset, whence);
+
+ if (res == (off_t)-1)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ g_vfs_job_seek_read_set_offset (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return;
+}
+
+static void
+do_query_info_on_read (GVfsBackend *backend,
+ GVfsJobQueryInfoRead *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat st = {0};
+ int res, saved_errno;
+ smbc_fstat_fn smbc_fstat;
+
+ smbc_fstat = smbc_getFunctionFstat (op_backend->smb_context);
+ res = smbc_fstat (op_backend->smb_context, (SMBCFILE *)handle, &st);
+ saved_errno = errno;
+
+ if (res == 0)
+ {
+ set_info_from_stat (op_backend, info, &st, NULL, matcher);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+
+}
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ ssize_t res;
+ smbc_close_fn smbc_close;
+
+ smbc_close = smbc_getFunctionClose (op_backend->smb_context);
+ res = smbc_close (op_backend->smb_context, (SMBCFILE *)handle);
+ if (res == -1)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+typedef struct {
+ SMBCFILE *file;
+ char *uri;
+ char *tmp_uri;
+ char *backup_uri;
+} SmbWriteHandle;
+
+static void
+smb_write_handle_free (SmbWriteHandle *handle)
+{
+ g_free (handle->uri);
+ g_free (handle->tmp_uri);
+ g_free (handle->backup_uri);
+ g_free (handle);
+}
+
+static void
+do_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *uri;
+ SMBCFILE *file;
+ SmbWriteHandle *handle;
+ smbc_open_fn smbc_open;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
+ file = smbc_open (op_backend->smb_context, uri,
+ O_CREAT|O_WRONLY|O_EXCL, 0666);
+ g_free (uri);
+
+ if (file == NULL)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ handle = g_new0 (SmbWriteHandle, 1);
+ handle->file = file;
+
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_write_set_handle (job, handle);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *uri;
+ SMBCFILE *file;
+ SmbWriteHandle *handle;
+ off_t initial_offset;
+ smbc_open_fn smbc_open;
+ smbc_lseek_fn smbc_lseek;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
+ file = smbc_open (op_backend->smb_context, uri,
+ O_CREAT|O_WRONLY|O_APPEND, 0666);
+ g_free (uri);
+
+ if (file == NULL)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ handle = g_new0 (SmbWriteHandle, 1);
+ handle->file = file;
+
+ smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
+ initial_offset = smbc_lseek (op_backend->smb_context, file,
+ 0, SEEK_CUR);
+ if (initial_offset == (off_t) -1)
+ g_vfs_job_open_for_write_set_can_seek (job, FALSE);
+ else
+ {
+ g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
+ }
+ g_vfs_job_open_for_write_set_handle (job, handle);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+
+static void
+random_chars (char *str, int len)
+{
+ int i;
+ const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ for (i = 0; i < len; i++)
+ str[i] = chars[g_random_int_range (0, strlen(chars))];
+}
+
+static char *
+get_dir_from_uri (const char *uri)
+{
+ const char *prefix_end;
+
+ prefix_end = uri + strlen (uri);
+
+ /* Skip slashes at end */
+ while (prefix_end > uri &&
+ *(prefix_end - 1) == '/')
+ prefix_end--;
+
+ /* Skip to next slash */
+ while (prefix_end > uri &&
+ *(prefix_end - 1) != '/')
+ prefix_end--;
+
+ return g_strndup (uri, prefix_end - uri);
+}
+
+static SMBCFILE *
+open_tmpfile (GVfsBackendSmb *backend,
+ const char *uri,
+ char **tmp_uri_out)
+{
+ char *dir_uri, *tmp_uri;
+ char filename[] = "~gvfXXXX.tmp";
+ SMBCFILE *file;
+ smbc_open_fn smbc_open;
+
+ dir_uri = get_dir_from_uri (uri);
+
+ do {
+ random_chars (filename + 4, 4);
+ tmp_uri = g_strconcat (dir_uri, filename, NULL);
+
+ smbc_open = smbc_getFunctionOpen (backend->smb_context);
+ file = smbc_open (backend->smb_context, tmp_uri,
+ O_CREAT|O_WRONLY|O_EXCL, 0666);
+ } while (file == NULL && errno == EEXIST);
+
+ g_free (dir_uri);
+
+ if (file)
+ {
+ *tmp_uri_out = tmp_uri;
+ return file;
+ }
+ else
+ {
+ g_free (tmp_uri);
+ return NULL;
+ }
+}
+
+static gboolean
+copy_file (GVfsBackendSmb *backend,
+ GVfsJob *job,
+ const char *from_uri,
+ const char *to_uri)
+{
+ SMBCFILE *from_file, *to_file;
+ char buffer[4096];
+ size_t buffer_size;
+ ssize_t res;
+ char *p;
+ gboolean succeeded;
+ smbc_open_fn smbc_open;
+ smbc_read_fn smbc_read;
+ smbc_write_fn smbc_write;
+ smbc_close_fn smbc_close;
+
+
+ from_file = NULL;
+ to_file = NULL;
+
+ succeeded = FALSE;
+
+ smbc_open = smbc_getFunctionOpen (backend->smb_context);
+ smbc_read = smbc_getFunctionRead (backend->smb_context);
+ smbc_write = smbc_getFunctionWrite (backend->smb_context);
+ smbc_close = smbc_getFunctionClose (backend->smb_context);
+
+ from_file = smbc_open (backend->smb_context, from_uri,
+ O_RDONLY, 0666);
+ if (from_file == NULL || g_vfs_job_is_cancelled (job))
+ goto out;
+
+ to_file = smbc_open (backend->smb_context, to_uri,
+ O_CREAT|O_WRONLY|O_TRUNC, 0666);
+
+ if (from_file == NULL || g_vfs_job_is_cancelled (job))
+ goto out;
+
+ while (1)
+ {
+
+ res = smbc_read (backend->smb_context, from_file,
+ buffer, sizeof(buffer));
+ if (res < 0 || g_vfs_job_is_cancelled (job))
+ goto out;
+ if (res == 0)
+ break; /* Succeeded */
+
+ buffer_size = res;
+ p = buffer;
+ while (buffer_size > 0)
+ {
+ res = smbc_write (backend->smb_context, to_file,
+ p, buffer_size);
+ if (res < 0 || g_vfs_job_is_cancelled (job))
+ goto out;
+ buffer_size -= res;
+ p += res;
+ }
+ }
+ succeeded = TRUE;
+
+ out:
+ if (to_file)
+ smbc_close (backend->smb_context, to_file);
+ if (from_file)
+ smbc_close (backend->smb_context, from_file);
+ return succeeded;
+}
+
+static char *
+create_etag (struct stat *statbuf)
+{
+ return g_strdup_printf ("%lu", (long unsigned int)statbuf->st_mtime);
+}
+
+static void
+do_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat original_stat;
+ int res;
+ char *uri, *tmp_uri, *backup_uri, *current_etag;
+ SMBCFILE *file;
+ GError *error = NULL;
+ SmbWriteHandle *handle;
+ smbc_open_fn smbc_open;
+ smbc_stat_fn smbc_stat;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ tmp_uri = NULL;
+ if (make_backup)
+ backup_uri = g_strconcat (uri, "~", NULL);
+ else
+ backup_uri = NULL;
+
+ smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+
+ file = smbc_open (op_backend->smb_context, uri,
+ O_CREAT|O_WRONLY|O_EXCL, 0);
+ if (file == NULL && errno != EEXIST)
+ {
+ int errsv = errno;
+
+ g_set_error_literal (&error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ g_strerror (errsv));
+ goto error;
+ }
+ else if (file == NULL && errno == EEXIST)
+ {
+ if (etag != NULL)
+ {
+ res = smbc_stat (op_backend->smb_context, uri, &original_stat);
+
+ if (res == 0)
+ {
+ current_etag = create_etag (&original_stat);
+ if (strcmp (etag, current_etag) != 0)
+ {
+ g_free (current_etag);
+ g_set_error_literal (&error,
+ G_IO_ERROR,
+ G_IO_ERROR_WRONG_ETAG,
+ _("The file was externally modified"));
+ goto error;
+ }
+ g_free (current_etag);
+ }
+ }
+
+ /* Backup strategy:
+ *
+ * By default we:
+ * 1) save to a tmp file (that doesn't exist already)
+ * 2) rename orig file to backup file
+ * (or delete it if no backup)
+ * 3) rename tmp file to orig file
+ *
+ * However, this can fail if we can't write to the directory.
+ * In that case we just truncate the file, after having
+ * copied directly to the backup filename.
+ */
+
+ file = open_tmpfile (op_backend, uri, &tmp_uri);
+ if (file == NULL)
+ {
+ if (make_backup)
+ {
+ if (!copy_file (op_backend, G_VFS_JOB (job), uri, backup_uri))
+ {
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ g_set_error_literal (&error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ else
+ g_set_error_literal (&error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("Backup file creation failed"));
+ goto error;
+ }
+ g_free (backup_uri);
+ backup_uri = NULL;
+ }
+
+ file = smbc_open (op_backend->smb_context, uri,
+ O_CREAT|O_WRONLY|O_TRUNC, 0);
+ if (file == NULL)
+ {
+ int errsv = errno;
+
+ g_set_error_literal (&error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ g_strerror (errsv));
+ goto error;
+ }
+ }
+ }
+ else
+ {
+ /* Doesn't exist. Just write away */
+ g_free (backup_uri);
+ backup_uri = NULL;
+ }
+
+ handle = g_new (SmbWriteHandle, 1);
+ handle->file = file;
+ handle->uri = uri;
+ handle->tmp_uri = tmp_uri;
+ handle->backup_uri = backup_uri;
+
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_write_set_handle (job, handle);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return;
+
+ error:
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_free (backup_uri);
+ g_free (tmp_uri);
+ g_free (uri);
+}
+
+
+static void
+do_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle _handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ SmbWriteHandle *handle = _handle;
+ ssize_t res;
+ smbc_write_fn smbc_write;
+
+ smbc_write = smbc_getFunctionWrite (op_backend->smb_context);
+ res = smbc_write (op_backend->smb_context, handle->file,
+ buffer, buffer_size);
+ if (res == -1)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ g_vfs_job_write_set_written_size (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_seek_on_write (GVfsBackend *backend,
+ GVfsJobSeekWrite *job,
+ GVfsBackendHandle _handle,
+ goffset offset,
+ GSeekType type)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ SmbWriteHandle *handle = _handle;
+ int whence;
+ off_t res;
+ smbc_lseek_fn smbc_lseek;
+
+ switch (type)
+ {
+ case G_SEEK_SET:
+ whence = SEEK_SET;
+ break;
+ case G_SEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case G_SEEK_END:
+ whence = SEEK_END;
+ break;
+ default:
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Unsupported seek type"));
+ return;
+ }
+
+ smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
+ res = smbc_lseek (op_backend->smb_context, handle->file, offset, whence);
+
+ if (res == (off_t)-1)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ else
+ {
+ g_vfs_job_seek_write_set_offset (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return;
+}
+
+static void
+do_query_info_on_write (GVfsBackend *backend,
+ GVfsJobQueryInfoWrite *job,
+ GVfsBackendHandle _handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat st = {0};
+ SmbWriteHandle *handle = _handle;
+ int res, saved_errno;
+ smbc_fstat_fn smbc_fstat;
+
+ smbc_fstat = smbc_getFunctionFstat (op_backend->smb_context);
+ res = smbc_fstat (op_backend->smb_context, handle->file, &st);
+ saved_errno = errno;
+
+ if (res == 0)
+ {
+ set_info_from_stat (op_backend, info, &st, NULL, matcher);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+
+}
+
+static void
+do_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle _handle)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ SmbWriteHandle *handle = _handle;
+ struct stat stat_at_close;
+ int stat_res;
+ ssize_t res;
+ smbc_fstat_fn smbc_fstat;
+ smbc_close_fn smbc_close;
+ smbc_unlink_fn smbc_unlink;
+ smbc_rename_fn smbc_rename;
+
+ smbc_fstat = smbc_getFunctionFstat (op_backend->smb_context);
+ smbc_close = smbc_getFunctionClose (op_backend->smb_context);
+ smbc_unlink = smbc_getFunctionUnlink (op_backend->smb_context);
+ smbc_rename = smbc_getFunctionRename (op_backend->smb_context);
+
+ stat_res = smbc_fstat (op_backend->smb_context, handle->file, &stat_at_close);
+
+ res = smbc_close (op_backend->smb_context, handle->file);
+
+ if (res == -1)
+ {
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+
+ if (handle->tmp_uri)
+ smbc_unlink (op_backend->smb_context, handle->tmp_uri);
+ goto out;
+ }
+
+ if (handle->tmp_uri)
+ {
+ if (handle->backup_uri)
+ {
+ res = smbc_rename (op_backend->smb_context, handle->uri,
+ op_backend->smb_context, handle->backup_uri);
+ if (res == -1)
+ {
+ int errsv = errno;
+
+ smbc_unlink (op_backend->smb_context, handle->tmp_uri);
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("Backup file creation failed: %s"), g_strerror (errsv));
+ goto out;
+ }
+ }
+ else
+ smbc_unlink (op_backend->smb_context, handle->uri);
+
+ res = smbc_rename (op_backend->smb_context, handle->tmp_uri,
+ op_backend->smb_context, handle->uri);
+ if (res == -1)
+ {
+ smbc_unlink (op_backend->smb_context, handle->tmp_uri);
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+ goto out;
+ }
+ }
+
+ if (stat_res == 0)
+ {
+ char *etag;
+ etag = create_etag (&stat_at_close);
+ g_vfs_job_close_write_set_etag (job, etag);
+ g_free (etag);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ out:
+ smb_write_handle_free (handle);
+}
+
+static void
+set_info_from_stat (GVfsBackendSmb *backend,
+ GFileInfo *info,
+ struct stat *statbuf,
+ const char *basename,
+ GFileAttributeMatcher *matcher)
+{
+ GFileType file_type;
+ GTimeVal t;
+ GIcon *icon;
+ char *content_type;
+ char *display_name;
+
+ if (basename)
+ {
+ g_file_info_set_name (info, basename);
+ if (*basename == '.')
+ g_file_info_set_is_hidden (info, TRUE);
+ }
+
+
+ if (basename != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
+ {
+ if (strcmp (basename, "/") == 0)
+ display_name = g_strdup_printf (_("%s on %s"), backend->share, backend->server);
+ else
+ display_name = g_filename_display_name (basename);
+
+ if (strstr (display_name, "\357\277\275") != NULL)
+ {
+ char *p = display_name;
+ display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL);
+ g_free (p);
+ }
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+
+ if (basename != NULL &&
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME))
+ {
+ char *edit_name = g_filename_display_name (basename);
+ g_file_info_set_edit_name (info, edit_name);
+ g_free (edit_name);
+ }
+
+
+ file_type = G_FILE_TYPE_UNKNOWN;
+
+ if (S_ISREG (statbuf->st_mode))
+ file_type = G_FILE_TYPE_REGULAR;
+ else if (S_ISDIR (statbuf->st_mode))
+ file_type = G_FILE_TYPE_DIRECTORY;
+ else if (S_ISCHR (statbuf->st_mode) ||
+ S_ISBLK (statbuf->st_mode) ||
+ S_ISFIFO (statbuf->st_mode)
+#ifdef S_ISSOCK
+ || S_ISSOCK (statbuf->st_mode)
+#endif
+ )
+ file_type = G_FILE_TYPE_SPECIAL;
+ else if (S_ISLNK (statbuf->st_mode))
+ file_type = G_FILE_TYPE_SYMBOLIC_LINK;
+
+ g_file_info_set_file_type (info, file_type);
+ g_file_info_set_size (info, statbuf->st_size);
+
+ t.tv_sec = statbuf->st_mtime;
+#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
+ t.tv_usec = statbuf->st_mtimensec / 1000;
+#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+ t.tv_usec = statbuf->st_mtim.tv_nsec / 1000;
+#else
+ t.tv_usec = 0;
+#endif
+ g_file_info_set_modification_time (info, &t);
+
+
+ if (g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE) ||
+ g_file_attribute_matcher_matches (matcher,
+ G_FILE_ATTRIBUTE_STANDARD_ICON))
+ {
+ icon = NULL;
+ if (S_ISDIR(statbuf->st_mode))
+ {
+ content_type = g_strdup ("inode/directory");
+ if (strcmp (basename, "/") == 0)
+ icon = g_themed_icon_new ("folder-remote");
+ else
+ icon = g_themed_icon_new ("folder");
+ }
+ else
+ {
+ content_type = g_content_type_guess (basename, NULL, 0, NULL);
+ if (content_type)
+ icon = g_content_type_get_icon (content_type);
+ }
+
+ if (content_type)
+ {
+ g_file_info_set_content_type (info, content_type);
+ g_free (content_type);
+ }
+
+ if (icon == NULL)
+ icon = g_themed_icon_new ("text-x-generic");
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+
+ /* Don't trust n_link, uid, gid, etc returned from libsmb, its just made up.
+ These are ok though: */
+
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE, statbuf->st_dev);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE, statbuf->st_ino);
+
+ /* If file is dos-readonly, libsmbclient doesn't set S_IWUSR, we use this to
+ trigger ACCESS_WRITE = FALSE: */
+ if (!(statbuf->st_mode & S_IWUSR))
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
+
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, statbuf->st_atime);
+#if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC)
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000);
+#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
+#endif
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED, statbuf->st_ctime);
+#if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC)
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000);
+#elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC)
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000);
+#endif
+
+ /* Libsmb sets the X bit on files to indicate some special things: */
+ if ((statbuf->st_mode & S_IFDIR) == 0) {
+
+ if (statbuf->st_mode & S_IXOTH)
+ g_file_info_set_is_hidden (info, TRUE);
+
+ if (statbuf->st_mode & S_IXUSR)
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_DOS_IS_ARCHIVE, TRUE);
+
+ if (statbuf->st_mode & S_IXGRP)
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_DOS_IS_SYSTEM, TRUE);
+ }
+
+ if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_ETAG_VALUE))
+ {
+ char *etag = create_etag (statbuf);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, etag);
+ g_free (etag);
+ }
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat st = {0};
+ char *uri;
+ int res, saved_errno;
+ char *basename;
+ smbc_stat_fn smbc_stat;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+ res = smbc_stat (op_backend->smb_context, uri, &st);
+ saved_errno = errno;
+ g_free (uri);
+
+ if (res == 0)
+ {
+ basename = g_path_get_basename (filename);
+ set_info_from_stat (op_backend, info, &st, basename, matcher);
+ g_free (basename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+
+}
+
+static void
+do_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "cifs");
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+
+static gboolean
+try_query_settable_attributes (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename)
+{
+ GFileAttributeInfoList *list;
+
+ list = g_file_attribute_info_list_new ();
+
+ /* TODO: Add all settable attributes here -- bug #559586 */
+ /* TODO: xattrs support? */
+
+ g_file_attribute_info_list_add (list,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_ATTRIBUTE_TYPE_UINT64,
+ G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+
+#if 0
+/* FIXME: disabled; despite chmod is supported, it makes no sense on samba shares and
+ libsmbclient lacks proper API to read unix file modes.
+ The struct stat->st_mode member is used for special Windows attributes. */
+ g_file_attribute_info_list_add (list,
+ G_FILE_ATTRIBUTE_UNIX_MODE,
+ G_FILE_ATTRIBUTE_TYPE_UINT32,
+ G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+#endif
+
+ g_vfs_job_query_attributes_set_list (job, list);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ g_file_attribute_info_list_unref (list);
+ return TRUE;
+}
+
+static void
+do_set_attribute (GVfsBackend *backend,
+ GVfsJobSetAttribute *job,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSmb *op_backend;
+ char *uri;
+ int res, errsv;
+ struct timeval tbuf[2];
+ smbc_utimes_fn smbc_utimes;
+#if 0
+ smbc_chmod_fn smbc_chmod;
+#endif
+
+
+ op_backend = G_VFS_BACKEND_SMB (backend);
+
+ if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED) != 0
+#if 0
+ && strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) != 0
+#endif
+ )
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation unsupported"));
+ return;
+ }
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ res = -1;
+
+ if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED) == 0)
+ {
+ smbc_utimes = smbc_getFunctionUtimes (op_backend->smb_context);
+ tbuf[1].tv_sec = (*(guint64 *)value_p); /* mtime */
+ tbuf[1].tv_usec = 0;
+ /* atime = mtime (atimes are usually disabled on desktop systems) */
+ tbuf[0].tv_sec = tbuf[1].tv_sec;
+ tbuf[0].tv_usec = 0;
+ res = smbc_utimes (op_backend->smb_context, uri, &tbuf[0]);
+ }
+#if 0
+ else
+ if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0)
+ {
+ smbc_chmod = smbc_getFunctionChmod (op_backend->smb_context);
+ res = smbc_chmod (op_backend->smb_context, uri, (*(guint32 *)value_p) & 0777);
+ }
+#endif
+
+ errsv = errno;
+ g_free (uri);
+
+ if (res != 0)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat st;
+ int res;
+ GError *error;
+ SMBCFILE *dir;
+ char dirents[1024*4];
+ struct smbc_dirent *dirp;
+ GList *files;
+ GFileInfo *info;
+ GString *uri;
+ int uri_start_len;
+ smbc_opendir_fn smbc_opendir;
+ smbc_getdents_fn smbc_getdents;
+ smbc_stat_fn smbc_stat;
+ smbc_closedir_fn smbc_closedir;
+
+ uri = create_smb_uri_string (op_backend->server, op_backend->share, filename);
+
+ smbc_opendir = smbc_getFunctionOpendir (op_backend->smb_context);
+ smbc_getdents = smbc_getFunctionGetdents (op_backend->smb_context);
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+ smbc_closedir = smbc_getFunctionClosedir (op_backend->smb_context);
+
+ dir = smbc_opendir (op_backend->smb_context, uri->str);
+
+ if (dir == NULL)
+ {
+ int errsv = errno;
+
+ error = NULL;
+ g_set_error_literal (&error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ g_strerror (errsv));
+ goto error;
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ if (uri->str[uri->len - 1] != '/')
+ g_string_append_c (uri, '/');
+ uri_start_len = uri->len;
+
+ while (TRUE)
+ {
+ files = NULL;
+
+ res = smbc_getdents (op_backend->smb_context, dir, (struct smbc_dirent *)dirents, sizeof (dirents));
+ if (res <= 0)
+ break;
+
+ dirp = (struct smbc_dirent *)dirents;
+ while (res > 0)
+ {
+ unsigned int dirlen;
+
+ /* TODO: Only do stat if required for flags */
+
+ if ((dirp->smbc_type == SMBC_DIR ||
+ dirp->smbc_type == SMBC_FILE ||
+ dirp->smbc_type == SMBC_LINK) &&
+ strcmp (dirp->name, ".") != 0 &&
+ strcmp (dirp->name, "..") != 0)
+ {
+ int stat_res;
+ g_string_truncate (uri, uri_start_len);
+ g_string_append_encoded (uri,
+ dirp->name,
+ SUB_DELIM_CHARS ":@/");
+
+ if (matcher == NULL ||
+ g_file_attribute_matcher_matches_only (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME))
+ {
+ info = g_file_info_new ();
+ g_file_info_set_name (info, dirp->name);
+ files = g_list_prepend (files, info);
+ }
+ else
+ {
+ stat_res = smbc_stat (op_backend->smb_context,
+ uri->str, &st);
+ if (stat_res == 0)
+ {
+ info = g_file_info_new ();
+ set_info_from_stat (op_backend, info, &st, dirp->name, matcher);
+ files = g_list_prepend (files, info);
+ }
+ }
+ }
+
+ dirlen = dirp->dirlen;
+ dirp = (struct smbc_dirent *) (((char *)dirp) + dirlen);
+ res -= dirlen;
+ }
+
+ if (files)
+ {
+ files = g_list_reverse (files);
+ g_vfs_job_enumerate_add_infos (job, files);
+ g_list_foreach (files, (GFunc)g_object_unref, NULL);
+ g_list_free (files);
+ }
+ }
+
+ res = smbc_closedir (op_backend->smb_context, dir);
+
+ g_vfs_job_enumerate_done (job);
+
+ g_string_free (uri, TRUE);
+ return;
+
+ error:
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ g_string_free (uri, TRUE);
+}
+
+static void
+do_set_display_name (GVfsBackend *backend,
+ GVfsJobSetDisplayName *job,
+ const char *filename,
+ const char *display_name)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *from_uri, *to_uri;
+ char *dirname, *new_path;
+ int res, errsv;
+ smbc_rename_fn smbc_rename;
+
+ dirname = g_path_get_dirname (filename);
+
+ /* TODO: display name is in utf8, atm we assume libsmb uris
+ are in utf8, but this might not be true if the user changed
+ the smb.conf file. Can we check this and convert? */
+
+ new_path = g_build_filename (dirname, display_name, NULL);
+ g_free (dirname);
+
+ from_uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ to_uri = create_smb_uri (op_backend->server, op_backend->share, new_path);
+
+ smbc_rename = smbc_getFunctionRename (op_backend->smb_context);
+ res = smbc_rename (op_backend->smb_context, from_uri,
+ op_backend->smb_context, to_uri);
+ errsv = errno;
+ g_free (from_uri);
+ g_free (to_uri);
+
+ if (res != 0)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ else
+ {
+ g_vfs_job_set_display_name_set_new_path (job, new_path);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ g_free (new_path);
+}
+
+static void
+do_delete (GVfsBackend *backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ struct stat statbuf;
+ char *uri;
+ int errsv, res;
+ smbc_stat_fn smbc_stat;
+ smbc_rmdir_fn smbc_rmdir;
+ smbc_unlink_fn smbc_unlink;
+
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+ smbc_rmdir = smbc_getFunctionRmdir (op_backend->smb_context);
+ smbc_unlink = smbc_getFunctionUnlink (op_backend->smb_context);
+
+ res = smbc_stat (op_backend->smb_context, uri, &statbuf);
+ if (res == -1)
+ {
+ errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error deleting file: %s"),
+ g_strerror (errsv));
+ g_free (uri);
+ return;
+ }
+
+ if (S_ISDIR (statbuf.st_mode))
+ res = smbc_rmdir (op_backend->smb_context, uri);
+ else
+ res = smbc_unlink (op_backend->smb_context, uri);
+ errsv = errno;
+ g_free (uri);
+
+ if (res != 0)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *uri;
+ int errsv, res;
+ smbc_mkdir_fn smbc_mkdir;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ smbc_mkdir = smbc_getFunctionMkdir (op_backend->smb_context);
+ res = smbc_mkdir (op_backend->smb_context, uri, 0666);
+ errsv = errno;
+ g_free (uri);
+
+ if (res != 0)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_move (GVfsBackend *backend,
+ GVfsJobMove *job,
+ const char *source,
+ const char *destination,
+ GFileCopyFlags flags,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *source_uri, *dest_uri, *backup_uri;
+ gboolean destination_exist, source_is_dir;
+ struct stat statbuf;
+ int res, errsv;
+ smbc_stat_fn smbc_stat;
+ smbc_rename_fn smbc_rename;
+ smbc_unlink_fn smbc_unlink;
+
+
+ source_uri = create_smb_uri (op_backend->server, op_backend->share, source);
+
+ smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+ smbc_rename = smbc_getFunctionRename (op_backend->smb_context);
+ smbc_unlink = smbc_getFunctionUnlink (op_backend->smb_context);
+
+ res = smbc_stat (op_backend->smb_context, source_uri, &statbuf);
+ if (res == -1)
+ {
+ errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error moving file: %s"),
+ g_strerror (errsv));
+ g_free (source_uri);
+ return;
+ }
+ else
+ source_is_dir = S_ISDIR (statbuf.st_mode);
+
+ dest_uri = create_smb_uri (op_backend->server, op_backend->share, destination);
+
+ destination_exist = FALSE;
+ res = smbc_stat (op_backend->smb_context, dest_uri, &statbuf);
+ if (res == 0)
+ {
+ destination_exist = TRUE; /* Target file exists */
+
+ if (flags & G_FILE_COPY_OVERWRITE)
+ {
+ /* Always fail on dirs, even with overwrite */
+ if (S_ISDIR (statbuf.st_mode))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_WOULD_MERGE,
+ _("Can't move directory over directory"));
+ g_free (source_uri);
+ g_free (dest_uri);
+ return;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ g_free (source_uri);
+ g_free (dest_uri);
+ return;
+ }
+ }
+
+ if (flags & G_FILE_COPY_BACKUP && destination_exist)
+ {
+ backup_uri = g_strconcat (dest_uri, "~", NULL);
+ res = smbc_rename (op_backend->smb_context, dest_uri,
+ op_backend->smb_context, backup_uri);
+ if (res == -1)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("Backup file creation failed"));
+ g_free (source_uri);
+ g_free (dest_uri);
+ g_free (backup_uri);
+ return;
+ }
+ g_free (backup_uri);
+ destination_exist = FALSE; /* It did, but no more */
+ }
+
+ if (source_is_dir && destination_exist && (flags & G_FILE_COPY_OVERWRITE))
+ {
+ /* Source is a dir, destination exists (and is not a dir, because that would have failed
+ earlier), and we're overwriting. Manually remove the target so we can do the rename. */
+ res = smbc_unlink (op_backend->smb_context, dest_uri);
+ errsv = errno;
+ if (res == -1)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error removing target file: %s"),
+ g_strerror (errsv));
+ g_free (source_uri);
+ g_free (dest_uri);
+ return;
+ }
+ }
+
+
+ res = smbc_rename (op_backend->smb_context, source_uri,
+ op_backend->smb_context, dest_uri);
+ errsv = errno;
+ g_free (source_uri);
+ g_free (dest_uri);
+
+ /* Catch moves across device boundaries */
+ if (res != 0)
+ {
+ if (errsv == EXDEV ||
+ /* Unfortunately libsmbclient doesn't correctly return EXDEV, but falls back
+ to EINVAL, so we try to guess when this happens: */
+ (errsv == EINVAL && source_is_dir))
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
+ _("Can't recursively move directory"));
+ else
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ }
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+#ifdef HAVE_GCONF
+ GConfClient *gclient;
+#endif
+
+ gobject_class->finalize = g_vfs_backend_smb_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->try_mount = try_mount;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->read = do_read;
+ backend_class->seek_on_read = do_seek_on_read;
+ backend_class->query_info_on_read = do_query_info_on_read;
+ backend_class->close_read = do_close_read;
+ backend_class->create = do_create;
+ backend_class->append_to = do_append_to;
+ backend_class->replace = do_replace;
+ backend_class->write = do_write;
+ backend_class->seek_on_write = do_seek_on_write;
+ backend_class->query_info_on_write = do_query_info_on_write;
+ backend_class->close_write = do_close_write;
+ backend_class->query_info = do_query_info;
+ backend_class->query_fs_info = do_query_fs_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->set_display_name = do_set_display_name;
+ backend_class->delete = do_delete;
+ backend_class->make_directory = do_make_directory;
+ backend_class->move = do_move;
+ backend_class->try_query_settable_attributes = try_query_settable_attributes;
+ backend_class->set_attribute = do_set_attribute;
+
+#ifdef HAVE_GCONF
+ gclient = gconf_client_get_default ();
+ if (gclient)
+ {
+ char *workgroup;
+
+ workgroup = gconf_client_get_string (gclient,
+ PATH_GCONF_GNOME_VFS_SMB_WORKGROUP, NULL);
+
+ if (workgroup && workgroup[0])
+ default_workgroup = workgroup;
+ else
+ g_free (workgroup);
+
+ g_object_unref (gclient);
+ }
+#endif
+
+}
+
+void
+g_vfs_smb_daemon_init (void)
+{
+ g_set_application_name (_("Windows Shares Filesystem Service"));
+}
diff --git a/trunk/daemon/gvfsbackendsmb.h b/trunk/daemon/gvfsbackendsmb.h
new file mode 100644
index 00000000..5f1a52b7
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsmb.h
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_SMB_H__
+#define __G_VFS_BACKEND_SMB_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_SMB (g_vfs_backend_smb_get_type ())
+#define G_VFS_BACKEND_SMB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_SMB, GVfsBackendSmb))
+#define G_VFS_BACKEND_SMB_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_SMB, GVfsBackendSmbClass))
+#define G_VFS_IS_BACKEND_SMB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_SMB))
+#define G_VFS_IS_BACKEND_SMB_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_SMB))
+#define G_VFS_BACKEND_SMB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_SMB, GVfsBackendSmbClass))
+
+typedef struct _GVfsBackendSmb GVfsBackendSmb;
+typedef struct _GVfsBackendSmbClass GVfsBackendSmbClass;
+
+struct _GVfsBackendSmbClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_smb_get_type (void) G_GNUC_CONST;
+
+#define BACKEND_SETUP_FUNC g_vfs_smb_daemon_init
+void g_vfs_smb_daemon_init (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_SMB_H__ */
diff --git a/trunk/daemon/gvfsbackendsmbbrowse.c b/trunk/daemon/gvfsbackendsmbbrowse.c
new file mode 100644
index 00000000..6d0c07e4
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsmbbrowse.c
@@ -0,0 +1,1502 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gvfsbackendsmbbrowse.h"
+#include "gvfsjobmountmountable.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfskeyring.h"
+#include "gmounttracker.h"
+
+#include <libsmbclient.h>
+#include "libsmb-compat.h"
+
+#ifdef HAVE_GCONF
+#include <gconf/gconf-client.h>
+#endif
+
+/* We load a default workgroup from gconf */
+#define PATH_GCONF_GNOME_VFS_SMB_WORKGROUP "/system/smb/workgroup"
+
+/* The magic "default workgroup" hostname */
+#define DEFAULT_WORKGROUP_NAME "X-GNOME-DEFAULT-WORKGROUP"
+
+/* Time in seconds before we mark dirents cache outdated */
+#define DEFAULT_CACHE_EXPIRATION_TIME 10
+
+
+#define PRINT_DEBUG
+
+#ifdef PRINT_DEBUG
+#define DEBUG(msg...) g_print("### SMB-BROWSE: " msg)
+#else
+#define DEBUG(...)
+#endif
+
+typedef struct {
+ unsigned int smbc_type;
+ char *name;
+ char *name_normalized;
+ char *name_utf8;
+ char *comment;
+} BrowseEntry;
+
+struct _GVfsBackendSmbBrowse
+{
+ GVfsBackend parent_instance;
+
+ char *user;
+ char *domain;
+ char *server;
+ char *mounted_server; /* server or DEFAULT_WORKGROUP_NAME */
+ SMBCCTX *smb_context;
+
+ char *last_user;
+ char *last_domain;
+ char *last_password;
+
+ GMountSource *mount_source;
+ int mount_try;
+ gboolean mount_try_again;
+ gboolean mount_cancelled;
+
+ gboolean password_in_keyring;
+ GPasswordSave password_save;
+
+ GMutex *entries_lock;
+ GMutex *update_cache_lock;
+ time_t last_entry_update;
+ GList *entries;
+ int entry_errno;
+};
+
+static char *default_workgroup = NULL;
+
+static GHashTable *server_cache = NULL;
+static GMountTracker *mount_tracker = NULL;
+
+typedef struct {
+ char *server_name;
+ char *share_name;
+ char *domain;
+ char *username;
+} CachedServer;
+
+G_DEFINE_TYPE (GVfsBackendSmbBrowse, g_vfs_backend_smb_browse, G_VFS_TYPE_BACKEND)
+
+static char *
+normalize_smb_name_helper (const char *name, gssize len, gboolean valid_utf8)
+{
+ if (valid_utf8)
+ return g_utf8_casefold (name, len);
+ else
+ return g_ascii_strdown (name, len);
+}
+
+static char *
+normalize_smb_name (const char *name, gssize len)
+{
+ gboolean valid_utf8;
+
+ valid_utf8 = g_utf8_validate (name, len, NULL);
+ return normalize_smb_name_helper (name, len, valid_utf8);
+}
+
+static char *
+smb_name_to_utf8 (const char *name, gboolean *valid_utf8_out)
+{
+ GString *string;
+ const gchar *remainder, *invalid;
+ gint remaining_bytes, valid_bytes;
+ gboolean valid_utf8;
+
+ remainder = name;
+ remaining_bytes = strlen (name);
+ valid_utf8 = TRUE;
+
+ string = g_string_sized_new (remaining_bytes);
+ while (remaining_bytes != 0)
+ {
+ if (g_utf8_validate (remainder, remaining_bytes, &invalid))
+ break;
+ valid_utf8 = FALSE;
+
+ valid_bytes = invalid - remainder;
+
+ g_string_append_len (string, remainder, valid_bytes);
+ /* append U+FFFD REPLACEMENT CHARACTER */
+ g_string_append (string, "\357\277\275");
+
+ remaining_bytes -= valid_bytes + 1;
+ remainder = invalid + 1;
+ }
+
+ g_string_append (string, remainder);
+
+ if (valid_utf8_out)
+ *valid_utf8_out = valid_utf8;
+
+ return g_string_free (string, FALSE);
+}
+
+static void
+browse_entry_free (BrowseEntry *entry)
+{
+ g_free (entry->name);
+ g_free (entry->comment);
+ g_free (entry);
+}
+
+static gboolean
+cached_server_equal (gconstpointer _a,
+ gconstpointer _b)
+{
+ const CachedServer *a = _a;
+ const CachedServer *b = _b;
+
+ return
+ strcmp (a->server_name, b->server_name) == 0 &&
+ strcmp (a->share_name, b->share_name) == 0 &&
+ strcmp (a->domain, b->domain) == 0 &&
+ strcmp (a->username, b->username) == 0;
+}
+
+static guint
+cached_server_hash (gconstpointer key)
+{
+ const CachedServer *server = key;
+
+ return
+ g_str_hash (server->server_name) ^
+ g_str_hash (server->share_name) ^
+ g_str_hash (server->domain) ^
+ g_str_hash (server->username);
+}
+
+static void
+cached_server_free (CachedServer *server)
+{
+ g_free (server->server_name);
+ g_free (server->share_name);
+ g_free (server->domain);
+ g_free (server->username);
+ g_free (server);
+}
+
+static void
+g_vfs_backend_smb_browse_finalize (GObject *object)
+{
+ GVfsBackendSmbBrowse *backend;
+
+ backend = G_VFS_BACKEND_SMB_BROWSE (object);
+
+ g_free (backend->user);
+ g_free (backend->domain);
+ g_free (backend->mounted_server);
+ g_free (backend->server);
+
+ g_mutex_free (backend->entries_lock);
+ g_mutex_free (backend->update_cache_lock);
+
+ smbc_free_context (backend->smb_context, TRUE);
+
+ g_list_foreach (backend->entries, (GFunc)browse_entry_free, NULL);
+ g_list_free (backend->entries);
+
+ if (G_OBJECT_CLASS (g_vfs_backend_smb_browse_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_smb_browse_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_smb_browse_init (GVfsBackendSmbBrowse *backend)
+{
+ backend->entries_lock = g_mutex_new ();
+ backend->update_cache_lock = g_mutex_new ();
+
+ if (mount_tracker == NULL)
+ mount_tracker = g_mount_tracker_new (NULL);
+}
+
+/**
+ * Authentication callback function type (method that includes context)
+ *
+ * Type for the the authentication function called by the library to
+ * obtain authentication credentals
+ *
+ * @param context Pointer to the smb context
+ * @param srv Server being authenticated to
+ * @param shr Share being authenticated to
+ * @param wg Pointer to buffer containing a "hint" for the
+ * workgroup to be authenticated. Should be filled in
+ * with the correct workgroup if the hint is wrong.
+ * @param wglen The size of the workgroup buffer in bytes
+ * @param un Pointer to buffer containing a "hint" for the
+ * user name to be use for authentication. Should be
+ * filled in with the correct workgroup if the hint is
+ * wrong.
+ * @param unlen The size of the username buffer in bytes
+ * @param pw Pointer to buffer containing to which password
+ * copied
+ * @param pwlen The size of the password buffer in bytes
+ *
+ */
+static void
+auth_callback (SMBCCTX *context,
+ const char *server_name, const char *share_name,
+ char *domain_out, int domainmaxlen,
+ char *username_out, int unmaxlen,
+ char *password_out, int pwmaxlen)
+{
+ GVfsBackendSmbBrowse *backend;
+ char *ask_password, *ask_user, *ask_domain;
+ gboolean handled, abort;
+
+ backend = smbc_getOptionUserData (context);
+
+ strncpy (password_out, "", pwmaxlen);
+
+ if (backend->domain)
+ strncpy (domain_out, backend->domain, domainmaxlen);
+ if (backend->user)
+ strncpy (username_out, backend->user, unmaxlen);
+
+ if (backend->mount_cancelled)
+ {
+ /* Don't prompt for credentials, let smbclient finish the mount loop */
+ strncpy (username_out, "ABORT", unmaxlen);
+ strncpy (password_out, "", pwmaxlen);
+ DEBUG ("auth_callback - mount_cancelled\n");
+ return;
+ }
+
+ if (backend->mount_source == NULL)
+ {
+ /* Not during mount, use last password */
+ if (backend->last_user)
+ strncpy (username_out, backend->last_user, unmaxlen);
+ if (backend->last_domain)
+ strncpy (domain_out, backend->last_domain, domainmaxlen);
+ if (backend->last_password)
+ strncpy (password_out, backend->last_password, pwmaxlen);
+ return;
+ }
+
+ if (backend->mount_try == 0 &&
+ backend->user == NULL &&
+ backend->domain == NULL)
+ {
+ /* Try again if kerberos login + anonymous fallback fails */
+ backend->mount_try_again = TRUE;
+ DEBUG ("auth_callback - anonymous pass\n");
+ }
+ else
+ {
+ gboolean in_keyring = FALSE;
+
+ DEBUG ("auth_callback - normal pass\n");
+
+ if (!backend->password_in_keyring)
+ {
+ in_keyring = g_vfs_keyring_lookup_password (backend->user,
+ backend->server,
+ backend->domain,
+ "smb",
+ NULL,
+ NULL,
+ 0,
+ &ask_user,
+ &ask_domain,
+ &ask_password);
+ backend->password_in_keyring = in_keyring;
+ }
+
+ if (!in_keyring)
+ {
+ GAskPasswordFlags flags = G_ASK_PASSWORD_NEED_PASSWORD;
+ char *message;
+
+ if (g_vfs_keyring_is_available ())
+ flags |= G_ASK_PASSWORD_SAVING_SUPPORTED;
+ if (backend->domain == NULL)
+ flags |= G_ASK_PASSWORD_NEED_DOMAIN;
+ if (backend->user == NULL)
+ flags |= G_ASK_PASSWORD_NEED_USERNAME;
+
+ DEBUG ("auth_callback - asking for password...\n");
+
+ /* translators: %s is a server name */
+ message = g_strdup_printf (_("Password required for %s"),
+ server_name);
+ handled = g_mount_source_ask_password (backend->mount_source,
+ message,
+ username_out,
+ domain_out,
+ flags,
+ &abort,
+ &ask_password,
+ &ask_user,
+ &ask_domain,
+ NULL,
+ &(backend->password_save));
+ g_free (message);
+ if (!handled)
+ goto out;
+
+ if (abort)
+ {
+ strncpy (username_out, "ABORT", unmaxlen);
+ strncpy (password_out, "", pwmaxlen);
+ backend->mount_cancelled = TRUE;
+ goto out;
+ }
+ }
+
+ /* Try again if this fails */
+ backend->mount_try_again = TRUE;
+
+ strncpy (password_out, ask_password, pwmaxlen);
+ if (ask_user && *ask_user)
+ strncpy (username_out, ask_user, unmaxlen);
+ if (ask_domain && *ask_domain)
+ strncpy (domain_out, ask_domain, domainmaxlen);
+
+ out:
+ g_free (ask_password);
+ g_free (ask_user);
+ g_free (ask_domain);
+ }
+
+ backend->last_user = g_strdup (username_out);
+ backend->last_domain = g_strdup (domain_out);
+ backend->last_password = g_strdup (password_out);
+ DEBUG ("auth_callback - out: last_user = '%s', last_domain = '%s'\n",
+ backend->last_user, backend->last_domain);
+}
+
+/* Add a server to the cache system
+ *
+ * @param c pointer to smb context
+ * @param srv pointer to server to add
+ * @param server server name
+ * @param share share name
+ * @param workgroup workgroup used to connect
+ * @param username username used to connect
+ * @return 0 on success. 1 on failure.
+ *
+ */
+static int
+add_cached_server (SMBCCTX *context, SMBCSRV *new,
+ const char *server_name, const char *share_name,
+ const char *domain, const char *username)
+{
+ CachedServer *cached_server;
+
+ cached_server = g_new (CachedServer, 1);
+ cached_server->server_name = g_strdup (server_name);
+ cached_server->share_name = g_strdup (share_name);
+ cached_server->domain = g_strdup (domain);
+ cached_server->username = g_strdup (username);
+
+ if (server_cache == NULL)
+ server_cache = g_hash_table_new_full (cached_server_hash, cached_server_equal,
+ (GDestroyNotify)cached_server_free, NULL);
+
+ g_hash_table_insert (server_cache, cached_server, new);
+
+ return 0;
+}
+
+static gboolean
+remove_cb (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ return value == user_data;
+}
+
+/* Remove cached server
+ *
+ * @param c pointer to smb context
+ * @param srv pointer to server to remove
+ * @return 0 when found and removed. 1 on failure.
+ *
+ */
+static int
+remove_cached_server (SMBCCTX * context, SMBCSRV * server)
+{
+ guint num;
+
+ if (server_cache)
+ {
+ num = g_hash_table_foreach_remove (server_cache, remove_cb, server);
+ if (num != 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Look up a server in the cache system
+ *
+ * @param c pointer to smb context
+ * @param server server name to match
+ * @param share share name to match
+ * @param workgroup workgroup to match
+ * @param username username to match
+ * @return pointer to SMBCSRV on success. NULL on failure.
+ *
+ */
+static SMBCSRV *
+get_cached_server (SMBCCTX * context,
+ const char *server_name, const char *share_name,
+ const char *domain, const char *username)
+{
+ const CachedServer key = {
+ (char *)server_name,
+ (char *)share_name,
+ (char *)domain,
+ (char *)username
+ };
+
+ if (server_cache)
+ return g_hash_table_lookup (server_cache, &key);
+ else
+ return NULL;
+}
+
+/* Try to remove all servers from the cache system and disconnect
+ *
+ * @param c pointer to smb context
+ *
+ * @return 0 when found and removed. 1 on failure.
+ *
+ */
+static int
+purge_cached (SMBCCTX * context)
+{
+ if (server_cache)
+ g_hash_table_remove_all (server_cache);
+
+ return 0;
+}
+
+#define SUB_DELIM_CHARS "!$&'()*+,;="
+
+static gboolean
+is_valid (char c, const char *reserved_chars_allowed)
+{
+ if (g_ascii_isalnum (c) ||
+ c == '-' ||
+ c == '.' ||
+ c == '_' ||
+ c == '~')
+ return TRUE;
+
+ if (reserved_chars_allowed &&
+ strchr (reserved_chars_allowed, c) != NULL)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+g_string_append_encoded (GString *string,
+ const char *encoded,
+ const char *encoded_end,
+ const char *reserved_chars_allowed)
+{
+ char c;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ if (encoded_end == NULL)
+ encoded_end = encoded + strlen (encoded);
+
+ while (encoded < encoded_end)
+ {
+ c = *encoded++;
+
+ if (is_valid (c, reserved_chars_allowed))
+ g_string_append_c (string, c);
+ else
+ {
+ g_string_append_c (string, '%');
+ g_string_append_c (string, hex[((guchar)c) >> 4]);
+ g_string_append_c (string, hex[((guchar)c) & 0xf]);
+ }
+ }
+}
+
+static gboolean
+update_cache (GVfsBackendSmbBrowse *backend, SMBCFILE *supplied_dir)
+{
+ GString *uri;
+ char dirents[1024*4];
+ struct smbc_dirent *dirp;
+ GList *entries;
+ int entry_errno;
+ SMBCFILE *dir;
+ int res;
+ smbc_opendir_fn smbc_opendir;
+ smbc_getdents_fn smbc_getdents;
+ smbc_closedir_fn smbc_closedir;
+
+
+ entries = NULL;
+ entry_errno = 0;
+ res = -1;
+
+ g_mutex_lock (backend->update_cache_lock);
+
+ DEBUG ("update_cache - updating...\n");
+
+ /* Update Cache */
+ uri = g_string_new ("smb://");
+
+ if (backend->server)
+ {
+ g_string_append_encoded (uri, backend->server, NULL, NULL);
+ g_string_append_c (uri, '/');
+ }
+
+ smbc_opendir = smbc_getFunctionOpendir (backend->smb_context);
+ smbc_getdents = smbc_getFunctionGetdents (backend->smb_context);
+ smbc_closedir = smbc_getFunctionClosedir (backend->smb_context);
+
+ dir = supplied_dir ? supplied_dir : smbc_opendir (backend->smb_context, uri->str);
+ g_string_free (uri, TRUE);
+ if (dir == NULL)
+ {
+ entry_errno = errno;
+ goto out;
+ }
+
+ while (TRUE)
+ {
+ res = smbc_getdents (backend->smb_context, dir, (struct smbc_dirent *)dirents, sizeof (dirents));
+ if (res <= 0)
+ {
+ if (res < 0)
+ DEBUG ("update_cache - smbc_getdents returned %d, errno = [%d] %s\n",
+ res, errno, g_strerror (errno));
+ break;
+ }
+
+ dirp = (struct smbc_dirent *)dirents;
+ while (res > 0)
+ {
+ unsigned int dirlen;
+
+ if (dirp->smbc_type != SMBC_IPC_SHARE &&
+ dirp->smbc_type != SMBC_COMMS_SHARE &&
+ dirp->smbc_type != SMBC_PRINTER_SHARE &&
+ strcmp (dirp->name, ".") != 0 &&
+ strcmp (dirp->name, "..") != 0)
+ {
+ BrowseEntry *entry = g_new (BrowseEntry, 1);
+ gboolean valid_utf8;
+
+ entry->smbc_type = dirp->smbc_type;
+ entry->name = g_strdup (dirp->name);
+ entry->name_utf8 = smb_name_to_utf8 (dirp->name, &valid_utf8);
+ entry->name_normalized = normalize_smb_name_helper (dirp->name, -1, valid_utf8);
+ entry->comment = smb_name_to_utf8 (dirp->comment, NULL);
+
+ entries = g_list_prepend (entries, entry);
+ }
+
+ dirlen = dirp->dirlen;
+ dirp = (struct smbc_dirent *) (((char *)dirp) + dirlen);
+ res -= dirlen;
+ }
+
+ entries = g_list_reverse (entries);
+ }
+
+ if (! supplied_dir)
+ smbc_closedir (backend->smb_context, dir);
+
+
+ out:
+
+ g_mutex_lock (backend->entries_lock);
+
+ /* Clear old cache */
+ g_list_foreach (backend->entries, (GFunc)browse_entry_free, NULL);
+ g_list_free (backend->entries);
+ backend->entries = entries;
+ backend->entry_errno = entry_errno;
+ backend->last_entry_update = time (NULL);
+
+ DEBUG ("update_cache - done.\n");
+
+ g_mutex_unlock (backend->entries_lock);
+ g_mutex_unlock (backend->update_cache_lock);
+
+ return (res >= 0);
+}
+
+static BrowseEntry *
+find_entry_unlocked (GVfsBackendSmbBrowse *backend,
+ const char *filename)
+{
+ BrowseEntry *entry, *found;
+ GList *l;
+ char *end;
+ int len;
+ char *normalized;
+
+ while (*filename == '/')
+ filename++;
+
+ end = strchr (filename, '/');
+ if (end)
+ {
+ len = end - filename;
+
+ while (*end == '/')
+ end++;
+
+ if (*end != 0)
+ return NULL;
+ }
+ else
+ len = strlen (filename);
+
+ /* First look for an exact filename match */
+ found = NULL;
+ for (l = backend->entries; l != NULL; l = l->next)
+ {
+ entry = l->data;
+
+ if (strncmp (filename, entry->name, len) == 0 &&
+ strlen (entry->name) == len)
+ {
+ found = entry;
+ break;
+ }
+ }
+
+ if (found == NULL)
+ {
+ /* That failed, try normalizing the filename */
+ normalized = normalize_smb_name (filename, len);
+
+ for (l = backend->entries; l != NULL; l = l->next)
+ {
+ entry = l->data;
+
+ if (strcmp (normalized, entry->name_normalized) == 0)
+ {
+ found = entry;
+ break;
+ }
+ }
+ g_free (normalized);
+ }
+
+ return found;
+}
+
+static GMountSpec *
+get_mount_spec_for_share (const char *server,
+ const char *share)
+{
+ GMountSpec *mount_spec;
+ char *normalized;
+
+ mount_spec = g_mount_spec_new ("smb-share");
+ normalized = normalize_smb_name (server, -1);
+ g_mount_spec_set (mount_spec, "server", normalized);
+ g_free (normalized);
+ normalized = normalize_smb_name (share, -1);
+ g_mount_spec_set (mount_spec, "share", normalized);
+ g_free (normalized);
+
+ return mount_spec;
+}
+
+static gboolean
+is_root (const char *filename)
+{
+ const char *p;
+
+ p = filename;
+ while (*p == '/')
+ p++;
+
+ return *p == 0;
+}
+
+static gboolean
+has_name (GVfsBackendSmbBrowse *backend,
+ const char *filename)
+{
+ gboolean res;
+
+ g_mutex_lock (backend->entries_lock);
+ res = (find_entry_unlocked (backend, filename) != NULL);
+ g_mutex_unlock (backend->entries_lock);
+ return res;
+}
+
+static gboolean
+cache_needs_updating (GVfsBackendSmbBrowse *backend)
+{
+ time_t now;
+ gboolean res;
+
+ /* If there's already cache update in progress, lock and wait until update is finished, then recheck */
+ g_mutex_lock (backend->update_cache_lock);
+ now = time (NULL);
+ res = now < backend->last_entry_update ||
+ (now - backend->last_entry_update) > DEFAULT_CACHE_EXPIRATION_TIME;
+ g_mutex_unlock (backend->update_cache_lock);
+
+ return res;
+}
+
+static void
+do_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+ SMBCCTX *smb_context;
+ SMBCFILE *dir;
+ char *display_name;
+ const char *debug;
+ int debug_val;
+ char *icon;
+ GString *uri;
+ gboolean res;
+ GMountSpec *browse_mount_spec;
+ smbc_opendir_fn smbc_opendir;
+ smbc_closedir_fn smbc_closedir;
+
+ smb_context = smbc_new_context ();
+ if (smb_context == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to allocate smb context");
+ return;
+ }
+
+ smbc_setOptionUserData (smb_context, backend);
+
+ debug = g_getenv ("GVFS_SMB_DEBUG");
+ if (debug)
+ debug_val = atoi (debug);
+ else
+#ifdef PRINT_DEBUG
+ debug_val = 4;
+#else
+ debug_val = 0;
+#endif
+
+ smbc_setDebug (smb_context, debug_val);
+ smbc_setFunctionAuthDataWithContext (smb_context, auth_callback);
+
+ smbc_setFunctionAddCachedServer (smb_context, add_cached_server);
+ smbc_setFunctionGetCachedServer (smb_context, get_cached_server);
+ smbc_setFunctionRemoveCachedServer (smb_context, remove_cached_server);
+ smbc_setFunctionPurgeCachedServers (smb_context, purge_cached);
+
+ /* FIXME: is strdup() still needed here? -- removed */
+ if (default_workgroup != NULL)
+ smbc_setWorkgroup (smb_context, default_workgroup);
+
+#ifndef DEPRECATED_SMBC_INTERFACE
+ smb_context->flags = 0;
+#endif
+
+ /* Initial settings:
+ * - use Kerberos (always)
+ * - in case of no username specified, try anonymous login
+ */
+ smbc_setOptionUseKerberos (smb_context, 1);
+ smbc_setOptionFallbackAfterKerberos (smb_context, op_backend->user != NULL);
+ smbc_setOptionNoAutoAnonymousLogin (smb_context, op_backend->user != NULL);
+
+#if 0
+ smbc_setOptionDebugToStderr (smb_context, 1);
+#endif
+
+ if (!smbc_init_context (smb_context))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to initialize smb context");
+ smbc_free_context (smb_context, FALSE);
+ return;
+ }
+
+ op_backend->smb_context = smb_context;
+
+ /* Convert DEFAULT_WORKGROUP_NAME to real domain */
+ if (op_backend->mounted_server != NULL &&
+ g_ascii_strcasecmp (op_backend->mounted_server, DEFAULT_WORKGROUP_NAME) == 0)
+ op_backend->server = g_strdup (smbc_getWorkgroup (smb_context));
+ else
+ op_backend->server = g_strdup (op_backend->mounted_server);
+
+ icon = NULL;
+ if (op_backend->server == NULL)
+ {
+ display_name = g_strdup (_("Windows Network"));
+ browse_mount_spec = g_mount_spec_new ("smb-network");
+ icon = "network-workgroup";
+ }
+ else
+ {
+ /* translators: Name for the location that lists the smb shares
+ availible on a server (%s is the name of the server) */
+ display_name = g_strdup_printf (_("Windows shares on %s"), op_backend->server);
+ browse_mount_spec = g_mount_spec_new ("smb-server");
+ g_mount_spec_set (browse_mount_spec, "server", op_backend->mounted_server);
+ icon = "network-server";
+ }
+
+ if (op_backend->user)
+ g_mount_spec_set (browse_mount_spec, "user", op_backend->user);
+ if (op_backend->domain)
+ g_mount_spec_set (browse_mount_spec, "domain", op_backend->domain);
+
+ g_vfs_backend_set_display_name (backend, display_name);
+ g_free (display_name);
+ if (icon)
+ g_vfs_backend_set_icon_name (backend, icon);
+ g_vfs_backend_set_user_visible (backend, FALSE);
+ g_vfs_backend_set_mount_spec (backend, browse_mount_spec);
+ g_mount_spec_unref (browse_mount_spec);
+
+ op_backend->mount_source = mount_source;
+ op_backend->mount_try = 0;
+ op_backend->password_save = G_PASSWORD_SAVE_NEVER;
+
+ smbc_opendir = smbc_getFunctionOpendir (smb_context);
+ smbc_closedir = smbc_getFunctionClosedir (smb_context);
+
+ uri = g_string_new ("smb://");
+
+ if (op_backend->server)
+ {
+ g_string_append_encoded (uri, op_backend->server, NULL, NULL);
+ g_string_append_c (uri, '/');
+ }
+
+ DEBUG ("do_mount - URI = %s\n", uri->str);
+
+ do
+ {
+ op_backend->mount_try_again = FALSE;
+ op_backend->mount_cancelled = FALSE;
+
+ DEBUG ("do_mount - try #%d \n", op_backend->mount_try);
+
+ dir = smbc_opendir (smb_context, uri->str);
+
+ DEBUG ("do_mount - [%s; %d] dir = %p, cancelled = %d, errno = [%d] '%s' \n",
+ uri->str, op_backend->mount_try, dir, op_backend->mount_cancelled,
+ errno, g_strerror (errno));
+
+ if (dir == NULL &&
+ (op_backend->mount_cancelled || (errno != EPERM && errno != EACCES)))
+ {
+ DEBUG ("do_mount - (errno != EPERM && errno != EACCES), breaking\n");
+ break;
+ }
+
+ if (dir != NULL)
+ {
+ /* Let update_cache() do enumeration, check for the smbc_getdents() result */
+ res = update_cache (op_backend, dir);
+ smbc_closedir (smb_context, dir);
+ DEBUG ("do_mount - login successful, res = %d\n", res);
+ if (res)
+ break;
+ }
+ else {
+ /* Purge the cache, we need to have clean playground for next auth try */
+ purge_cached (smb_context);
+ }
+
+ /* The first round is Kerberos-only. Only if this fails do we enable
+ * NTLMSSP fallback (turning off anonymous fallback, which we've
+ * already tried and failed with).
+ */
+ if (op_backend->mount_try == 0)
+ {
+ DEBUG ("do_mount - after anon, enabling NTLMSSP fallback\n");
+ smbc_setOptionFallbackAfterKerberos (op_backend->smb_context, 1);
+ smbc_setOptionNoAutoAnonymousLogin (op_backend->smb_context, 1);
+ }
+ op_backend->mount_try++;
+ }
+ while (op_backend->mount_try_again);
+
+ g_string_free (uri, TRUE);
+
+ op_backend->mount_source = NULL;
+
+ if (dir == NULL)
+ {
+ if (op_backend->mount_cancelled)
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Password dialog cancelled"));
+ else
+ /* TODO: Error from errno? */
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ /* translators: We tried to mount a windows (samba) share, but failed */
+ _("Failed to retrieve share list from server"));
+
+ return;
+ }
+
+ g_vfs_keyring_save_password (op_backend->last_user,
+ op_backend->server,
+ op_backend->last_domain,
+ "smb",
+ NULL,
+ NULL,
+ 0,
+ op_backend->last_password,
+ op_backend->password_save);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+ const char *server;
+ const char *user, *domain;
+
+ if (strcmp (g_mount_spec_get_type (mount_spec), "smb-network") == 0)
+ server = NULL;
+ else
+ {
+ server = g_mount_spec_get (mount_spec, "server");
+ if (server == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "No server specified for smb-server share");
+ return TRUE;
+ }
+ }
+
+ user = g_mount_spec_get (mount_spec, "user");
+ domain = g_mount_spec_get (mount_spec, "domain");
+
+ if (is_automount &&
+ ((user != NULL) || (domain != NULL)))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Can't automount smb browsing with specified user or domain");
+ return TRUE;
+ }
+
+ op_backend->user = g_strdup (user);
+ op_backend->domain = g_strdup (domain);
+ op_backend->mounted_server = g_strdup (server);
+
+ return FALSE;
+}
+
+static void
+run_mount_mountable (GVfsBackendSmbBrowse *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source)
+{
+ BrowseEntry *entry;
+ GError *error = NULL;
+ GMountSpec *mount_spec;
+
+ g_mutex_lock (backend->entries_lock);
+
+ entry = find_entry_unlocked (backend, filename);
+
+ if (entry)
+ {
+ if (backend->server != NULL &&
+ entry->smbc_type == SMBC_FILE_SHARE)
+ {
+ mount_spec = get_mount_spec_for_share (backend->server, entry->name);
+ g_vfs_job_mount_mountable_set_target (job, mount_spec, "/", TRUE);
+ g_mount_spec_unref (mount_spec);
+ }
+ else
+ g_set_error_literal (&error,
+ G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ _("The file is not a mountable"));
+ }
+ else
+ g_set_error_literal (&error,
+ G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+
+ g_mutex_unlock (backend->entries_lock);
+
+ if (error)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_mount_mountable (GVfsBackend *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ update_cache (op_backend, NULL);
+
+ run_mount_mountable (op_backend,
+ job,
+ filename,
+ mount_source);
+}
+
+static gboolean
+try_mount_mountable (GVfsBackend *backend,
+ GVfsJobMountMountable *job,
+ const char *filename,
+ GMountSource *mount_source)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ if (is_root (filename))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ _("The file is not a mountable"));
+ return TRUE;
+ }
+
+ if (cache_needs_updating (op_backend))
+ return FALSE;
+
+ run_mount_mountable (op_backend,
+ job,
+ filename,
+ mount_source);
+ return TRUE;
+}
+
+static void
+run_open_for_read (GVfsBackendSmbBrowse *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ if (has_name (backend, filename))
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("Not a regular file"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+}
+
+static void
+do_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ update_cache (op_backend, NULL);
+
+ run_open_for_read (op_backend, job, filename);
+}
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ if (cache_needs_updating (op_backend))
+ return FALSE;
+
+ run_open_for_read (op_backend, job, filename);
+
+ return TRUE;
+}
+
+static gboolean
+try_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Invalid argument");
+
+ return TRUE;
+}
+
+static gboolean
+try_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Invalid argument");
+ return TRUE;
+}
+
+static gboolean
+try_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Invalid argument");
+ return TRUE;
+}
+
+static void
+get_file_info_from_entry (GVfsBackendSmbBrowse *backend, BrowseEntry *entry, GFileInfo *info)
+{
+ GMountSpec *mount_spec;
+ GString *uri;
+ GIcon *icon;
+
+ g_file_info_set_name (info, entry->name);
+ g_file_info_set_display_name (info, entry->name_utf8);
+ g_file_info_set_edit_name (info, entry->name_utf8);
+ g_file_info_set_attribute_string (info, "smb::comment", entry->comment);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
+
+ icon = NULL;
+ if (entry->smbc_type == SMBC_WORKGROUP)
+ icon = g_themed_icon_new ("network-workgroup");
+ else if (entry->smbc_type == SMBC_SERVER)
+ icon = g_themed_icon_new ("network-server");
+ else
+ icon = g_themed_icon_new ("folder-remote");
+
+ if (icon)
+ {
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+ }
+
+ mount_spec = NULL;
+ if (backend->server)
+ {
+ /* browsing server/workgroup */
+ if (entry->smbc_type == SMBC_WORKGROUP ||
+ entry->smbc_type == SMBC_SERVER)
+ {
+ uri = g_string_new ("smb://");
+ g_string_append_encoded (uri, entry->name, NULL, NULL);
+ g_string_append_c (uri, '/');
+ }
+ else
+ {
+ mount_spec = get_mount_spec_for_share (backend->server, entry->name);
+
+ uri = g_string_new ("smb://");
+ g_string_append_encoded (uri, backend->server, NULL, NULL);
+ g_string_append_c (uri, '/');
+ g_string_append_encoded (uri, entry->name, NULL, NULL);
+ }
+ }
+ else
+ {
+ /* browsing network */
+ uri = g_string_new ("smb://");
+ g_string_append_encoded (uri, entry->name, NULL, NULL);
+ g_string_append_c (uri, '/');
+
+ /* these are auto-mounted, so no CAN_MOUNT/UNMOUNT */
+ }
+
+ if (mount_spec)
+ {
+ g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE);
+ if (g_mount_tracker_has_mount_spec (mount_tracker, mount_spec))
+ {
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, FALSE);
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, TRUE);
+ }
+ else
+ {
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, TRUE);
+ g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, FALSE);
+ }
+ g_mount_spec_unref (mount_spec);
+ }
+ else
+ g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT);
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, uri->str);
+ g_string_free (uri, TRUE);
+}
+
+static void
+run_query_info (GVfsBackendSmbBrowse *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ BrowseEntry *entry;
+
+ g_mutex_lock (backend->entries_lock);
+
+ entry = find_entry_unlocked (backend, filename);
+
+ if (entry)
+ get_file_info_from_entry (backend, entry, info);
+
+ g_mutex_unlock (backend->entries_lock);
+
+ if (entry)
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ update_cache (op_backend, NULL);
+
+ run_query_info (op_backend, job, filename, info, matcher);
+}
+
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+ GIcon *icon;
+
+ if (is_root (filename))
+ {
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_name (info, "/");
+ g_file_info_set_display_name (info, g_vfs_backend_get_display_name (backend));
+ icon = g_vfs_backend_get_icon (backend);
+ if (icon != NULL)
+ g_file_info_set_icon (info, icon);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+ }
+
+ if (cache_needs_updating (op_backend))
+ return FALSE;
+
+ run_query_info (op_backend, job, filename, info, matcher);
+
+ return TRUE;
+}
+
+static void
+run_enumerate (GVfsBackendSmbBrowse *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher)
+{
+ GList *files, *l;
+ GFileInfo *info;
+
+ if (!is_root (filename))
+ {
+ if (has_name (backend, filename))
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY,
+ _("Not a directory"));
+ else
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ return;
+ }
+
+ /* TODO: limit requested to what we support */
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ files = NULL;
+ g_mutex_lock (backend->entries_lock);
+ for (l = backend->entries; l != NULL; l = l->next)
+ {
+ BrowseEntry *entry = l->data;
+
+ info = g_file_info_new ();
+ get_file_info_from_entry (backend, entry, info);
+
+ files = g_list_prepend (files, info);
+ }
+ g_mutex_unlock (backend->entries_lock);
+
+ files = g_list_reverse (files);
+
+ g_vfs_job_enumerate_add_infos (job, files);
+ g_list_foreach (files, (GFunc)g_object_unref, NULL);
+ g_list_free (files);
+
+ g_vfs_job_enumerate_done (job);
+}
+
+static void
+do_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ update_cache (op_backend, NULL);
+
+ run_enumerate (op_backend, job, filename, matcher);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend);
+
+ if (cache_needs_updating (op_backend))
+ return FALSE;
+
+ run_enumerate (op_backend, job, filename, matcher);
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_smb_browse_class_init (GVfsBackendSmbBrowseClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+#ifdef HAVE_GCONF
+ GConfClient *gclient;
+#endif
+
+ gobject_class->finalize = g_vfs_backend_smb_browse_finalize;
+
+ backend_class->mount = do_mount;
+ backend_class->try_mount = try_mount;
+ backend_class->mount_mountable = do_mount_mountable;
+ backend_class->try_mount_mountable = try_mount_mountable;
+ backend_class->open_for_read = do_open_for_read;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_read = try_read;
+ backend_class->try_seek_on_read = try_seek_on_read;
+ backend_class->try_close_read = try_close_read;
+ backend_class->query_info = do_query_info;
+ backend_class->try_query_info = try_query_info;
+ backend_class->enumerate = do_enumerate;
+ backend_class->try_enumerate = try_enumerate;
+
+#ifdef HAVE_GCONF
+ gclient = gconf_client_get_default ();
+ if (gclient)
+ {
+ char *workgroup;
+
+ workgroup = gconf_client_get_string (gclient,
+ PATH_GCONF_GNOME_VFS_SMB_WORKGROUP, NULL);
+
+ if (workgroup && workgroup[0])
+ default_workgroup = workgroup;
+ else
+ g_free (workgroup);
+
+ g_object_unref (gclient);
+ }
+#endif
+
+ DEBUG ("g_vfs_backend_smb_browse_class_init - default workgroup = '%s'\n", default_workgroup);
+}
+
+void
+g_vfs_smb_browse_daemon_init (void)
+{
+ g_set_application_name (_("Windows Network Filesystem Service"));
+}
diff --git a/trunk/daemon/gvfsbackendsmbbrowse.h b/trunk/daemon/gvfsbackendsmbbrowse.h
new file mode 100644
index 00000000..4c013437
--- /dev/null
+++ b/trunk/daemon/gvfsbackendsmbbrowse.h
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_SMB_BROWSE_H__
+#define __G_VFS_BACKEND_SMB_BROWSE_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_SMB_BROWSE (g_vfs_backend_smb_browse_get_type ())
+#define G_VFS_BACKEND_SMB_BROWSE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_SMB_BROWSE, GVfsBackendSmbBrowse))
+#define G_VFS_BACKEND_SMB_BROWSE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_SMB_BROWSE, GVfsBackendSmbBrowseClass))
+#define G_VFS_IS_BACKEND_SMB_BROWSE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_SMB_BROWSE))
+#define G_VFS_IS_BACKEND_SMB_BROWSE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_SMB_BROWSE))
+#define G_VFS_BACKEND_SMB_BROWSE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_SMB_BROWSE, GVfsBackendSmbBrowseClass))
+
+typedef struct _GVfsBackendSmbBrowse GVfsBackendSmbBrowse;
+typedef struct _GVfsBackendSmbBrowseClass GVfsBackendSmbBrowseClass;
+
+struct _GVfsBackendSmbBrowseClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_smb_browse_get_type (void) G_GNUC_CONST;
+
+#define BACKEND_SETUP_FUNC g_vfs_smb_browse_daemon_init
+void g_vfs_smb_browse_daemon_init (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_SMB_BROWSE_H__ */
diff --git a/trunk/daemon/gvfsbackendtest.c b/trunk/daemon/gvfsbackendtest.c
new file mode 100644
index 00000000..ccc6e3af
--- /dev/null
+++ b/trunk/daemon/gvfsbackendtest.c
@@ -0,0 +1,592 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gvfsbackendtest.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobwrite.h"
+#include "gvfsjobopenforwrite.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsjobqueryinfowrite.h"
+
+G_DEFINE_TYPE (GVfsBackendTest, g_vfs_backend_test, G_VFS_TYPE_BACKEND)
+
+static void
+g_vfs_backend_test_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (g_vfs_backend_test_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_backend_test_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_test_init (GVfsBackendTest *test_backend)
+{
+ GVfsBackend *backend = G_VFS_BACKEND (test_backend);
+ GMountSpec *mount_spec;
+
+ g_vfs_backend_set_display_name (backend, "test");
+
+ mount_spec = g_mount_spec_new ("test");
+ g_vfs_backend_set_mount_spec (backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+}
+
+
+static gboolean
+try_mount (GVfsBackend *backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+}
+
+static gboolean
+open_idle_cb (gpointer data)
+{
+ GVfsJobOpenForRead *job = data;
+ int fd;
+
+ if (g_vfs_job_is_cancelled (G_VFS_JOB (job)))
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ return FALSE;
+ }
+
+ fd = g_open (job->filename, O_RDONLY);
+ if (fd == -1)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "Error opening file %s: %s",
+ job->filename, g_strerror (errsv));
+ }
+ else
+ {
+ g_vfs_job_open_for_read_set_can_seek (job, TRUE);
+ g_vfs_job_open_for_read_set_handle (job, GINT_TO_POINTER (fd));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ return FALSE;
+}
+
+static void
+open_read_cancelled_cb (GVfsJob *job, gpointer data)
+{
+ guint tag = GPOINTER_TO_INT (data);
+
+ g_print ("open_read_cancelled_cb\n");
+
+ if (g_source_remove (tag))
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+}
+
+static gboolean
+try_open_for_read (GVfsBackend *backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GError *error;
+
+ g_print ("try_open_for_read (%s)\n", filename);
+
+ if (strcmp (filename, "/fail") == 0)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Test error");
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ }
+ else
+ {
+ guint tag = g_timeout_add (0, open_idle_cb, job);
+ g_signal_connect (job, "cancelled", (GCallback)open_read_cancelled_cb, GINT_TO_POINTER (tag));
+ }
+
+ return TRUE;
+}
+
+static gboolean
+read_idle_cb (gpointer data)
+{
+ GVfsJobRead *job = data;
+ int fd;
+ ssize_t res;
+
+ fd = GPOINTER_TO_INT (job->handle);
+
+ res = read (fd, job->buffer, job->bytes_requested);
+
+ if (res == -1)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "Error reading from file: %s",
+ g_strerror (errsv));
+ }
+ else
+ {
+ g_vfs_job_read_set_size (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return FALSE;
+}
+
+static void
+read_cancelled_cb (GVfsJob *job, gpointer data)
+{
+ guint tag = GPOINTER_TO_INT (job->backend_data);
+
+ g_source_remove (tag);
+ g_vfs_job_failed (job, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+}
+
+static gboolean
+try_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ guint tag;
+
+ g_print ("read (%"G_GSIZE_FORMAT")\n", bytes_requested);
+
+ tag = g_timeout_add (0, read_idle_cb, job);
+ G_VFS_JOB (job)->backend_data = GINT_TO_POINTER (tag);
+ g_signal_connect (job, "cancelled", (GCallback)read_cancelled_cb, NULL);
+
+ return TRUE;
+}
+
+static void
+do_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ int whence;
+ int fd;
+ off_t final_offset;
+
+ g_print ("seek_on_read (%d, %u)\n", (int)offset, type);
+
+ switch (type)
+ {
+ default:
+ case G_SEEK_SET:
+ whence = SEEK_SET;
+ break;
+ case G_SEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case G_SEEK_END:
+ whence = SEEK_END;
+ break;
+ }
+
+
+ fd = GPOINTER_TO_INT (handle);
+
+ final_offset = lseek (fd, offset, whence);
+
+ if (final_offset == (off_t)-1)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "Error seeking in file: %s",
+ g_strerror (errsv));
+ }
+ else
+ {
+ g_vfs_job_seek_read_set_offset (job, offset);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_query_info_on_read (GVfsBackend *backend,
+ GVfsJobQueryInfoRead *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ int fd, res;
+ struct stat statbuf;
+
+ fd = GPOINTER_TO_INT (handle);
+
+ res = fstat (fd, &statbuf);
+
+ if (res == -1)
+ {
+ int errsv = errno;
+
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ "Error querying info in file: %s",
+ g_strerror (errsv));
+ }
+ else
+ {
+ g_file_info_set_size (info, statbuf.st_size);
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE,
+ statbuf.st_dev);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, statbuf.st_mtime);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, statbuf.st_atime);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED, statbuf.st_ctime);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ int fd;
+
+ g_print ("close ()\n");
+
+ fd = GPOINTER_TO_INT (handle);
+ close(fd);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+do_query_info (GVfsBackend *backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GFile *file;
+ GFileInfo *info2;
+ GError *error;
+ GVfs *local_vfs;
+
+ g_print ("do_get_file_info (%s)\n", filename);
+
+ local_vfs = g_vfs_get_local ();
+ file = g_vfs_get_file_for_path (local_vfs, filename);
+
+ error = NULL;
+ info2 = g_file_query_info (file, job->attributes, flags,
+ NULL, &error);
+
+ if (info2)
+ {
+ g_file_info_copy_into (info2, info);
+ g_object_unref (info2);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+
+ g_object_unref (file);
+}
+
+static void
+do_create (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GFile *file;
+ GFileOutputStream *out;
+ GError *error;
+
+ file = g_vfs_get_file_for_path (g_vfs_get_local (),
+ filename);
+
+ error = NULL;
+ out = g_file_create (file, flags, G_VFS_JOB (job)->cancellable, &error);
+ g_object_unref (file);
+ if (out)
+ {
+ g_vfs_job_open_for_write_set_can_seek (job, FALSE);
+ g_vfs_job_open_for_write_set_handle (job, out);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+do_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GFile *file;
+ GFileOutputStream *out;
+ GError *error;
+
+ file = g_vfs_get_file_for_path (g_vfs_get_local (),
+ filename);
+
+ error = NULL;
+ out = g_file_append_to (file, flags, G_VFS_JOB (job)->cancellable, &error);
+ g_object_unref (file);
+ if (out)
+ {
+ g_vfs_job_open_for_write_set_can_seek (job, FALSE);
+ g_vfs_job_open_for_write_set_handle (job, out);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+do_replace (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ const char *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags)
+{
+ GFile *file;
+ GFileOutputStream *out;
+ GError *error;
+
+ file = g_vfs_get_file_for_path (g_vfs_get_local (),
+ filename);
+
+ error = NULL;
+ out = g_file_replace (file,
+ etag, make_backup,
+ flags, G_VFS_JOB (job)->cancellable,
+ &error);
+ g_object_unref (file);
+ if (out)
+ {
+ g_vfs_job_open_for_write_set_can_seek (job, FALSE);
+ g_vfs_job_open_for_write_set_handle (job, out);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+ else
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+}
+
+static void
+do_close_write (GVfsBackend *backend,
+ GVfsJobCloseWrite *job,
+ GVfsBackendHandle handle)
+{
+ GFileOutputStream *out;
+ GError *error;
+ char *etag;
+
+ out = (GFileOutputStream *)handle;
+
+ error = NULL;
+ if (!g_output_stream_close (G_OUTPUT_STREAM (out),
+ G_VFS_JOB (job)->cancellable,
+ &error))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ {
+ etag = g_file_output_stream_get_etag (out);
+
+ if (etag)
+ {
+ g_vfs_job_close_write_set_etag (job, etag);
+ g_free (etag);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ g_object_unref (out);
+}
+
+static void
+do_write (GVfsBackend *backend,
+ GVfsJobWrite *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize buffer_size)
+{
+ GFileOutputStream *out;
+ GError *error;
+ gssize res;
+
+ g_print ("do_write\n");
+
+ out = (GFileOutputStream *)handle;
+
+ error = NULL;
+ res = g_output_stream_write (G_OUTPUT_STREAM (out),
+ buffer, buffer_size,
+ G_VFS_JOB (job)->cancellable,
+ &error);
+ if (res < 0)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ {
+ g_vfs_job_write_set_written_size (job, res);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static void
+do_query_info_on_write (GVfsBackend *backend,
+ GVfsJobQueryInfoWrite *job,
+ GVfsBackendHandle handle,
+ GFileInfo *info,
+ GFileAttributeMatcher *attribute_matcher)
+{
+ GFileOutputStream *out;
+ GError *error;
+ GFileInfo *info2;
+
+ g_print ("do_query_info_on_write\n");
+
+ out = (GFileOutputStream *)handle;
+
+ error = NULL;
+ info2 = g_file_output_stream_query_info (out, job->attributes,
+ G_VFS_JOB (job)->cancellable,
+ &error);
+ if (info2 == NULL)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ {
+ g_file_info_copy_into (info2, info);
+ g_object_unref (info2);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *matcher,
+ GFileQueryInfoFlags flags)
+{
+ GFileInfo *info1, *info2;
+ GList *l;
+
+ g_print ("try_enumerate (%s)\n", filename);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ info1 = g_file_info_new ();
+ info2 = g_file_info_new ();
+ g_file_info_set_name (info1, "file1");
+ g_file_info_set_file_type (info1, G_FILE_TYPE_REGULAR);
+ g_file_info_set_name (info2, "file2");
+ g_file_info_set_file_type (info2, G_FILE_TYPE_REGULAR);
+
+ l = NULL;
+ l = g_list_append (l, info1);
+ l = g_list_append (l, info2);
+
+ g_vfs_job_enumerate_add_infos (job, l);
+
+ g_list_free (l);
+ g_object_unref (info1);
+ g_object_unref (info2);
+
+ g_vfs_job_enumerate_done (job);
+
+ return TRUE;
+}
+
+static void
+g_vfs_backend_test_class_init (GVfsBackendTestClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_backend_test_finalize;
+
+ backend_class->try_mount = try_mount;
+ backend_class->try_open_for_read = try_open_for_read;
+ backend_class->try_read = try_read;
+ backend_class->seek_on_read = do_seek_on_read;
+ backend_class->query_info_on_read = do_query_info_on_read;
+ backend_class->close_read = do_close_read;
+
+ backend_class->replace = do_replace;
+ backend_class->create = do_create;
+ backend_class->append_to = do_append_to;
+ backend_class->write = do_write;
+ backend_class->query_info_on_write = do_query_info_on_write;
+ backend_class->close_write = do_close_write;
+
+ backend_class->query_info = do_query_info;
+ backend_class->try_enumerate = try_enumerate;
+}
diff --git a/trunk/daemon/gvfsbackendtest.h b/trunk/daemon/gvfsbackendtest.h
new file mode 100644
index 00000000..cfba8287
--- /dev/null
+++ b/trunk/daemon/gvfsbackendtest.h
@@ -0,0 +1,56 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_BACKEND_TEST_H__
+#define __G_VFS_BACKEND_TEST_H__
+
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_TEST (g_vfs_backend_test_get_type ())
+#define G_VFS_BACKEND_TEST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_TEST, GVfsBackendTest))
+#define G_VFS_BACKEND_TEST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_TEST, GVfsBackendTestClass))
+#define G_VFS_IS_BACKEND_TEST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_TEST))
+#define G_VFS_IS_BACKEND_TEST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_TEST))
+#define G_VFS_BACKEND_TEST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_TEST, GVfsBackendTestClass))
+
+typedef struct _GVfsBackendTest GVfsBackendTest;
+typedef struct _GVfsBackendTestClass GVfsBackendTestClass;
+
+struct _GVfsBackendTest
+{
+ GVfsBackend parent_instance;
+};
+
+struct _GVfsBackendTestClass
+{
+ GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_test_get_type (void) G_GNUC_CONST;
+
+GVfsBackendTest *g_vfs_backend_test_new (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_TEST_H__ */
diff --git a/trunk/daemon/gvfsbackendtrash.c b/trunk/daemon/gvfsbackendtrash.c
new file mode 100644
index 00000000..27b14570
--- /dev/null
+++ b/trunk/daemon/gvfsbackendtrash.c
@@ -0,0 +1,872 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "gvfsbackendtrash.h"
+
+#include <glib/gi18n.h> /* _() */
+#include <string.h>
+
+#include "trashlib/trashwatcher.h"
+#include "trashlib/trashitem.h"
+
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobqueryfsinfo.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobseekread.h"
+#include "gvfsjobread.h"
+
+typedef GVfsBackendClass GVfsBackendTrashClass;
+
+struct OPAQUE_TYPE__GVfsBackendTrash
+{
+ GVfsBackend parent_instance;
+
+ GVfsMonitor *file_monitor;
+ GVfsMonitor *dir_monitor;
+
+ TrashWatcher *watcher;
+ TrashRoot *root;
+
+ guint thaw_timeout_id;
+};
+
+G_DEFINE_TYPE (GVfsBackendTrash, g_vfs_backend_trash, G_VFS_TYPE_BACKEND);
+
+static GVfsMonitor *
+trash_backend_get_file_monitor (GVfsBackendTrash *backend,
+ gboolean create)
+{
+ if (backend->file_monitor == NULL && create == FALSE)
+ return NULL;
+
+ else if (backend->file_monitor == NULL)
+ {
+ /* 'create' is only ever set in the main thread, so we will have
+ * no possibility here for creating more than one new monitor.
+ */
+ if (backend->dir_monitor == NULL)
+ trash_watcher_watch (backend->watcher);
+
+ backend->file_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
+ }
+
+ return g_object_ref (backend->file_monitor);
+}
+
+static GVfsMonitor *
+trash_backend_get_dir_monitor (GVfsBackendTrash *backend,
+ gboolean create)
+{
+ if (backend->dir_monitor == NULL && create == FALSE)
+ return NULL;
+
+ else if (backend->dir_monitor == NULL)
+ {
+ /* 'create' is only ever set in the main thread, so we will have
+ * no possibility here for creating more than one new monitor.
+ */
+ if (backend->file_monitor == NULL)
+ trash_watcher_watch (backend->watcher);
+
+ backend->dir_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
+ }
+
+ return g_object_ref (backend->dir_monitor);
+}
+
+static void
+trash_backend_item_created (TrashItem *item,
+ gpointer user_data)
+{
+ GVfsBackendTrash *backend = user_data;
+ GVfsMonitor *monitor;
+
+ monitor = trash_backend_get_dir_monitor (backend, FALSE);
+
+ if (monitor)
+ {
+ char *slashname;
+
+ slashname = g_strconcat ("/", trash_item_get_escaped_name (item), NULL);
+
+ g_vfs_monitor_emit_event (monitor, G_FILE_MONITOR_EVENT_CREATED,
+ slashname, NULL);
+ g_object_unref (monitor);
+ g_free (slashname);
+ }
+}
+
+static void
+trash_backend_item_deleted (TrashItem *item,
+ gpointer user_data)
+{
+ GVfsBackendTrash *backend = user_data;
+ GVfsMonitor *monitor;
+
+ monitor = trash_backend_get_dir_monitor (backend, FALSE);
+
+ if (monitor)
+ {
+ char *slashname;
+
+ slashname = g_strconcat ("/", trash_item_get_escaped_name (item), NULL);
+ g_vfs_monitor_emit_event (monitor, G_FILE_MONITOR_EVENT_DELETED,
+ slashname, NULL);
+ g_object_unref (monitor);
+ g_free (slashname);
+ }
+}
+
+static void
+trash_backend_item_count_changed (gpointer user_data)
+{
+ GVfsBackendTrash *backend = user_data;
+ GVfsMonitor *file_monitor;
+ GVfsMonitor *dir_monitor;
+
+ file_monitor = trash_backend_get_file_monitor (backend, FALSE);
+ dir_monitor = trash_backend_get_dir_monitor (backend, FALSE);
+
+ if (file_monitor)
+ {
+ g_vfs_monitor_emit_event (file_monitor,
+ G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED,
+ "/", NULL);
+
+ g_object_unref (file_monitor);
+ }
+
+ if (dir_monitor)
+ {
+ g_vfs_monitor_emit_event (dir_monitor,
+ G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED,
+ "/", NULL);
+
+ g_object_unref (dir_monitor);
+ }
+}
+
+
+static GFile *
+trash_backend_get_file (GVfsBackendTrash *backend,
+ const char *filename,
+ TrashItem **item_ret,
+ gboolean *is_toplevel,
+ GError **error)
+{
+ const char *slash;
+ gboolean is_top;
+ TrashItem *item;
+ GFile *file;
+
+ file = NULL;
+ filename++;
+
+ slash = strchr (filename, '/');
+ is_top = slash == NULL;
+
+ if (is_toplevel)
+ *is_toplevel = is_top;
+
+ if (!is_top)
+ {
+ char *toplevel;
+
+ g_assert (slash[1]);
+
+ toplevel = g_strndup (filename, slash - filename);
+ if ((item = trash_root_lookup_item (backend->root, toplevel)))
+ {
+ file = trash_item_get_file (item);
+ file = g_file_get_child (file, slash + 1);
+
+ if (item_ret)
+ *item_ret = item;
+ else
+ trash_item_unref (item);
+ }
+
+ g_free (toplevel);
+ }
+ else
+ {
+ if ((item = trash_root_lookup_item (backend->root, filename)))
+ {
+ file = g_object_ref (trash_item_get_file (item));
+
+ if (item_ret)
+ *item_ret = item;
+ else
+ trash_item_unref (item);
+ }
+ }
+
+ if (file == NULL)
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("No such file or directory"));
+
+ return file;
+}
+
+/* ======================= method implementations ======================= */
+static gboolean
+trash_backend_open_for_read (GVfsBackend *vfs_backend,
+ GVfsJobOpenForRead *job,
+ const char *filename)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+ GError *error = NULL;
+
+ if (filename[1] == '\0')
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
+ _("Can't open directory"));
+
+ else
+ {
+ GFile *real;
+
+ real = trash_backend_get_file (backend, filename, NULL, NULL, &error);
+
+ if (real)
+ {
+ GFileInputStream *stream;
+
+ stream = g_file_read (real, NULL, &error);
+ g_object_unref (real);
+
+ if (stream)
+ {
+ g_vfs_job_open_for_read_set_handle (job, stream);
+ g_vfs_job_open_for_read_set_can_seek (job, TRUE);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+ }
+ }
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_read (GVfsBackend *backend,
+ GVfsJobRead *job,
+ GVfsBackendHandle handle,
+ char *buffer,
+ gsize bytes_requested)
+{
+ GError *error = NULL;
+ gssize bytes;
+
+ bytes = g_input_stream_read (handle, buffer, bytes_requested,
+ NULL, &error);
+
+ if (bytes >= 0)
+ {
+ g_vfs_job_read_set_size (job, bytes);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_seek_on_read (GVfsBackend *backend,
+ GVfsJobSeekRead *job,
+ GVfsBackendHandle handle,
+ goffset offset,
+ GSeekType type)
+{
+ GError *error = NULL;
+
+ if (g_seekable_seek (handle, offset, type, NULL, &error))
+ {
+ g_vfs_job_seek_read_set_offset (job, g_seekable_tell (handle));
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_close_read (GVfsBackend *backend,
+ GVfsJobCloseRead *job,
+ GVfsBackendHandle handle)
+{
+ GError *error = NULL;
+
+ if (g_input_stream_close (handle, NULL, &error))
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_object_unref (handle);
+
+ return TRUE;
+ }
+
+ g_object_unref (handle);
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_thaw_callback (gpointer user_data)
+{
+ GVfsBackendTrash *backend = user_data;
+
+ trash_root_thaw (backend->root);
+
+ backend->thaw_timeout_id = 0;
+ return FALSE;
+}
+
+static void
+trash_backend_schedule_thaw (GVfsBackendTrash *backend)
+{
+ if (backend->thaw_timeout_id)
+ g_source_remove (backend->thaw_timeout_id);
+
+ backend->thaw_timeout_id = g_timeout_add (200,
+ trash_backend_thaw_callback,
+ backend);
+}
+
+static gboolean
+trash_backend_delete (GVfsBackend *vfs_backend,
+ GVfsJobDelete *job,
+ const char *filename)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+ GError *error = NULL;
+ g_debug ("before job: %d\n", G_OBJECT(job)->ref_count);
+
+ if (filename[1] == '\0')
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("The trash folder may not be deleted"));
+ else
+ {
+ gboolean is_toplevel;
+ TrashItem *item;
+ GFile *real;
+
+ real = trash_backend_get_file (backend, filename,
+ &item, &is_toplevel, &error);
+
+ if (real)
+ {
+ /* not interested in the 'real', but the item */
+ g_object_unref (real);
+
+ if (!is_toplevel)
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Items in the trash may not be modified"));
+
+ else
+ {
+ if (trash_item_delete (item, &error))
+ {
+ trash_backend_schedule_thaw (backend);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ trash_item_unref (item);
+
+ return TRUE;
+ }
+ }
+
+ trash_item_unref (item);
+ }
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_pull (GVfsBackend *vfs_backend,
+ GVfsJobPull *job,
+ const gchar *source,
+ const gchar *local_path,
+ GFileCopyFlags flags,
+ gboolean remove_source,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+ GError *error = NULL;
+
+ if (source[1] == '\0')
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("The trash folder may not be deleted"));
+ else
+ {
+ gboolean is_toplevel;
+ TrashItem *item;
+ GFile *real;
+
+ real = trash_backend_get_file (backend, source, &item,
+ &is_toplevel, &error);
+
+ if (real)
+ {
+ if (remove_source && !is_toplevel)
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+ _("Items in the trash may not be modified"));
+
+ else
+ {
+ GFile *destination;
+ gboolean it_worked;
+
+ destination = g_file_new_for_path (local_path);
+
+ if (remove_source)
+ it_worked = trash_item_restore (item, destination, &error);
+ else
+ it_worked = g_file_copy (real, destination, flags,
+ NULL, NULL, NULL, &error);
+
+ g_object_unref (destination);
+
+ if (it_worked)
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ trash_item_unref (item);
+ g_object_unref (real);
+
+ return TRUE;
+ }
+ }
+
+ trash_item_unref (item);
+ g_object_unref (real);
+ }
+
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+
+ return TRUE;
+}
+
+static void
+trash_backend_add_info (TrashItem *item,
+ GFileInfo *info,
+ gboolean is_toplevel)
+{
+ if (is_toplevel)
+ {
+ const gchar *delete_date;
+ GFile *original;
+
+ g_assert (item != NULL);
+
+ original = trash_item_get_original (item);
+
+ if (original)
+ {
+ gchar *basename, *path;
+
+ path = g_file_get_path (original);
+ basename = g_filename_display_basename (path);
+
+ g_file_info_set_display_name (info, basename);
+ g_file_info_set_attribute_byte_string (info,
+ "trash::orig-path",
+ path);
+ g_free (basename);
+ g_free (path);
+ }
+
+ delete_date = trash_item_get_delete_date (item);
+
+ if (delete_date)
+ g_file_info_set_attribute_string (info,
+ "trash::deletion-date",
+ delete_date);
+ }
+
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ FALSE);
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
+ FALSE);
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME,
+ FALSE);
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+ FALSE);
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE,
+ is_toplevel);
+}
+
+static void
+trash_backend_enumerate_root (GVfsBackendTrash *backend,
+ GVfsJobEnumerate *job,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GList *items, *node;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ items = trash_root_get_items (backend->root);
+
+ for (node = items; node; node = node->next)
+ {
+ TrashItem *item = node->data;
+ GFileInfo *info;
+
+ info = g_file_query_info (trash_item_get_file (item),
+ job->attributes, flags, NULL, NULL);
+
+ if (info)
+ {
+ GFile *original;
+
+ g_file_info_set_attribute_mask (info, attribute_matcher);
+
+ g_file_info_set_name (info, trash_item_get_escaped_name (item));
+ trash_backend_add_info (item, info, TRUE);
+
+ original = trash_item_get_original (item);
+
+ if (original)
+ {
+ char *basename;
+
+ basename = g_file_get_basename (original);
+
+ /* XXX utf8 */
+ g_file_info_set_display_name (info, basename);
+ g_free (basename);
+ }
+
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ trash_item_unref (item);
+ }
+
+ g_vfs_job_enumerate_done (job);
+ g_list_free (items);
+}
+
+static void
+trash_backend_enumerate_non_root (GVfsBackendTrash *backend,
+ GVfsJobEnumerate *job,
+ const gchar *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GError *error = NULL;
+ GFile *real;
+
+ real = trash_backend_get_file (backend, filename, NULL, NULL, &error);
+
+ if (real)
+ {
+ GFileEnumerator *enumerator;
+
+ enumerator = g_file_enumerate_children (real, job->attributes,
+ job->flags, NULL, &error);
+ g_object_unref (real);
+
+ if (enumerator)
+ {
+ GFileInfo *info;
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ while ((info = g_file_enumerator_next_file (enumerator,
+ NULL, &error)))
+ {
+ trash_backend_add_info (NULL, info, FALSE);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
+ }
+
+ /* error from next_file? ignore. */
+ if (error)
+ g_error_free (error);
+
+ g_vfs_job_enumerate_done (job);
+ g_object_unref (enumerator);
+ return;
+ }
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+}
+
+static gboolean
+trash_backend_enumerate (GVfsBackend *vfs_backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+
+ g_assert (filename[0] == '/');
+
+ trash_watcher_rescan (backend->watcher);
+
+ if (filename[1])
+ trash_backend_enumerate_non_root (backend, job, filename,
+ attribute_matcher, flags);
+ else
+ trash_backend_enumerate_root (backend, job, attribute_matcher, flags);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_mount (GVfsBackend *vfs_backend,
+ GVfsJobMount *job,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+
+ backend->file_monitor = NULL;
+ backend->dir_monitor = NULL;
+ backend->root = trash_root_new (trash_backend_item_created,
+ trash_backend_item_deleted,
+ trash_backend_item_count_changed,
+ backend);
+ backend->watcher = trash_watcher_new (backend->root);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_query_info (GVfsBackend *vfs_backend,
+ GVfsJobQueryInfo *job,
+ const char *filename,
+ GFileQueryInfoFlags flags,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+
+ g_assert (filename[0] == '/');
+
+ if (filename[1])
+ {
+ GError *error = NULL;
+ gboolean is_toplevel;
+ TrashItem *item;
+ GFile *real;
+
+ real = trash_backend_get_file (backend, filename,
+ &item, &is_toplevel, &error);
+
+ if (real)
+ {
+ GFileInfo *real_info;
+
+ real_info = g_file_query_info (real, job->attributes,
+ flags, NULL, &error);
+ g_object_unref (real);
+
+ if (real_info)
+ {
+ g_file_info_copy_into (real_info, info);
+ trash_backend_add_info (item, info, is_toplevel);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ trash_item_unref (item);
+ g_object_unref (real_info);
+
+ return TRUE;
+ }
+
+ trash_item_unref (item);
+ }
+
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ }
+ else
+ {
+ GIcon *icon;
+ int n_items;
+
+ n_items = trash_root_get_n_items (backend->root);
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_name (info, "/");
+ /* Translators: this is the display name of the backend */
+ g_file_info_set_display_name (info, _("Trash"));
+ g_file_info_set_content_type (info, "inode/directory");
+
+ icon = g_themed_icon_new (n_items ? "user-trash-full" : "user-trash");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+
+ g_file_info_set_attribute_uint32 (info, "trash::item-count", n_items);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ }
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_query_fs_info (GVfsBackend *vfs_backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ g_file_info_set_attribute_string (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_TYPE,
+ "trash");
+
+ g_file_info_set_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_READONLY,
+ FALSE);
+
+ g_file_info_set_attribute_uint32 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW,
+ G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_create_dir_monitor (GVfsBackend *vfs_backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+ GVfsMonitor *monitor;
+
+ if (filename[1])
+ monitor = g_vfs_monitor_new (vfs_backend);
+ else
+ monitor = trash_backend_get_dir_monitor (backend, TRUE);
+
+ g_vfs_job_create_monitor_set_monitor (job, monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_object_unref (monitor);
+
+ return TRUE;
+}
+
+static gboolean
+trash_backend_create_file_monitor (GVfsBackend *vfs_backend,
+ GVfsJobCreateMonitor *job,
+ const char *filename,
+ GFileMonitorFlags flags)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
+ GVfsMonitor *monitor;
+
+ if (filename[1])
+ monitor = g_vfs_monitor_new (vfs_backend);
+ else
+ monitor = trash_backend_get_file_monitor (backend, TRUE);
+
+ g_vfs_job_create_monitor_set_monitor (job, monitor);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_object_unref (monitor);
+
+ return TRUE;
+}
+
+static void
+trash_backend_finalize (GObject *object)
+{
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (object);
+
+ /* get rid of these first to stop a flood of event notifications
+ * from being emitted while we're tearing down the TrashWatcher
+ */
+ if (backend->file_monitor)
+ g_object_unref (backend->file_monitor);
+ backend->file_monitor = NULL;
+
+ if (backend->dir_monitor)
+ g_object_unref (backend->dir_monitor);
+ backend->dir_monitor = NULL;
+
+ trash_watcher_free (backend->watcher);
+ trash_root_free (backend->root);
+}
+
+static void
+g_vfs_backend_trash_init (GVfsBackendTrash *backend)
+{
+ GVfsBackend *vfs_backend = G_VFS_BACKEND (backend);
+ GMountSpec *mount_spec;
+
+ /* translators: This is the name of the backend */
+ g_vfs_backend_set_display_name (vfs_backend, _("Trash"));
+ g_vfs_backend_set_icon_name (vfs_backend, "user-trash");
+ g_vfs_backend_set_user_visible (vfs_backend, FALSE);
+
+ mount_spec = g_mount_spec_new ("trash");
+ g_vfs_backend_set_mount_spec (vfs_backend, mount_spec);
+ g_mount_spec_unref (mount_spec);
+}
+
+static void
+g_vfs_backend_trash_class_init (GVfsBackendTrashClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (class);
+
+ gobject_class->finalize = trash_backend_finalize;
+
+ backend_class->try_mount = trash_backend_mount;
+ backend_class->try_open_for_read = trash_backend_open_for_read;
+ backend_class->try_read = trash_backend_read;
+ backend_class->try_seek_on_read = trash_backend_seek_on_read;
+ backend_class->try_close_read = trash_backend_close_read;
+ backend_class->try_query_info = trash_backend_query_info;
+ backend_class->try_query_fs_info = trash_backend_query_fs_info;
+ backend_class->try_enumerate = trash_backend_enumerate;
+ backend_class->try_delete = trash_backend_delete;
+ backend_class->try_pull = trash_backend_pull;
+ backend_class->try_create_dir_monitor = trash_backend_create_dir_monitor;
+ backend_class->try_create_file_monitor = trash_backend_create_file_monitor;
+}
diff --git a/trunk/daemon/gvfsbackendtrash.h b/trunk/daemon/gvfsbackendtrash.h
new file mode 100644
index 00000000..5550884b
--- /dev/null
+++ b/trunk/daemon/gvfsbackendtrash.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef _gvfsbackendtrash_h_
+#define _gvfsbackendtrash_h_
+
+#include <gvfsbackend.h>
+
+#define G_VFS_TYPE_BACKEND_TRASH (g_vfs_backend_trash_get_type ())
+#define G_VFS_BACKEND_TRASH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ G_VFS_TYPE_BACKEND_TRASH, \
+ GVfsBackendTrash))
+
+typedef struct OPAQUE_TYPE__GVfsBackendTrash GVfsBackendTrash;
+GType g_vfs_backend_trash_get_type (void);
+
+#endif /* _gvfsbackendtrash_h_ */
diff --git a/trunk/daemon/gvfschannel.c b/trunk/daemon/gvfschannel.c
new file mode 100644
index 00000000..0a2b5848
--- /dev/null
+++ b/trunk/daemon/gvfschannel.c
@@ -0,0 +1,720 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gvfsreadchannel.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsdaemonutils.h>
+#include <gvfsjobcloseread.h>
+#include <gvfsjobclosewrite.h>
+#include <gvfsfileinfo.h>
+
+static void g_vfs_channel_job_source_iface_init (GVfsJobSourceIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GVfsChannel, g_vfs_channel, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_VFS_TYPE_JOB_SOURCE,
+ g_vfs_channel_job_source_iface_init))
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+
+enum {
+ PROP_0,
+ PROP_BACKEND
+};
+
+typedef struct
+{
+ GVfsChannel *channel;
+ GInputStream *command_stream;
+ char buffer[G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE];
+ int buffer_size;
+ char *data;
+ gsize data_len;
+ gsize data_pos;
+} RequestReader;
+
+typedef struct {
+ guint32 command;
+ guint32 arg1;
+ guint32 arg2;
+ guint32 seq_nr;
+
+ gpointer data;
+ gsize data_len;
+ gboolean cancelled;
+} Request;
+
+struct _GVfsChannelPrivate
+{
+ GVfsBackend *backend;
+ gboolean connection_closed;
+ GInputStream *command_stream;
+ GOutputStream *reply_stream;
+ int remote_fd;
+
+ GVfsBackendHandle backend_handle;
+ GVfsJob *current_job;
+ guint32 current_job_seq_nr;
+
+ GList *queued_requests;
+
+ RequestReader *request_reader;
+
+ char reply_buffer[G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE];
+ int reply_buffer_pos;
+
+ const char *output_data; /* Owned by job */
+ gsize output_data_size;
+ gsize output_data_pos;
+};
+
+static void start_request_reader (GVfsChannel *channel);
+static void g_vfs_channel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void g_vfs_channel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+
+static void
+g_vfs_channel_finalize (GObject *object)
+{
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (object);
+
+ if (channel->priv->current_job)
+ g_object_unref (channel->priv->current_job);
+ channel->priv->current_job = NULL;
+
+ if (channel->priv->reply_stream)
+ g_object_unref (channel->priv->reply_stream);
+ channel->priv->reply_stream = NULL;
+
+ if (channel->priv->request_reader)
+ channel->priv->request_reader->channel = NULL;
+ channel->priv->request_reader = NULL;
+
+ if (channel->priv->command_stream)
+ g_object_unref (channel->priv->command_stream);
+ channel->priv->command_stream = NULL;
+
+ if (channel->priv->remote_fd != -1)
+ close (channel->priv->remote_fd);
+
+ if (channel->priv->backend)
+ g_object_unref (channel->priv->backend);
+
+ g_assert (channel->priv->backend_handle == NULL);
+
+ if (G_OBJECT_CLASS (g_vfs_channel_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_channel_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_channel_job_source_iface_init (GVfsJobSourceIface *iface)
+{
+}
+
+static void
+g_vfs_channel_class_init (GVfsChannelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GVfsChannelPrivate));
+
+ gobject_class->finalize = g_vfs_channel_finalize;
+ gobject_class->set_property = g_vfs_channel_set_property;
+ gobject_class->get_property = g_vfs_channel_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_BACKEND,
+ g_param_spec_object ("backend",
+ P_("Backend"),
+ P_("Backend implementation to use"),
+ G_VFS_TYPE_BACKEND,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_vfs_channel_init (GVfsChannel *channel)
+{
+ int socket_fds[2];
+ int ret;
+
+ channel->priv = G_TYPE_INSTANCE_GET_PRIVATE (channel,
+ G_VFS_TYPE_CHANNEL,
+ GVfsChannelPrivate);
+ channel->priv->remote_fd = -1;
+
+ ret = socketpair (AF_UNIX, SOCK_STREAM, 0, socket_fds);
+ if (ret == -1)
+ g_warning ("Error creating socket pair: %d\n", errno);
+ else
+ {
+ channel->priv->command_stream = g_unix_input_stream_new (socket_fds[0], TRUE);
+ channel->priv->reply_stream = g_unix_output_stream_new (socket_fds[0], FALSE);
+ channel->priv->remote_fd = socket_fds[1];
+
+ start_request_reader (channel);
+ }
+}
+
+static void
+g_vfs_channel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsChannel *channel = G_VFS_CHANNEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_BACKEND:
+ if (channel->priv->backend)
+ g_object_unref (channel->priv->backend);
+ channel->priv->backend = G_VFS_BACKEND (g_value_dup_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_channel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsChannel *channel = G_VFS_CHANNEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_BACKEND:
+ g_value_set_object (value, channel->priv->backend);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_channel_connection_closed (GVfsChannel *channel)
+{
+ GVfsChannelClass *class;
+
+ if (channel->priv->connection_closed)
+ return;
+ channel->priv->connection_closed = TRUE;
+
+ if (channel->priv->current_job == NULL &&
+ channel->priv->backend_handle != NULL)
+ {
+ class = G_VFS_CHANNEL_GET_CLASS (channel);
+
+ channel->priv->current_job = class->close (channel);
+ channel->priv->current_job_seq_nr = 0;
+ g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (channel), channel->priv->current_job);
+ }
+ /* Otherwise we'll close when current_job is finished */
+}
+
+static void
+request_reader_free (RequestReader *reader)
+{
+ g_object_unref (reader->command_stream);
+ g_free (reader->data);
+ g_free (reader);
+}
+
+static gboolean
+start_queued_request (GVfsChannel *channel)
+{
+ GVfsChannelClass *class;
+ Request *req;
+ GVfsJob *job;
+ GError *error;
+ gboolean started_job;
+
+ started_job = FALSE;
+
+ class = G_VFS_CHANNEL_GET_CLASS (channel);
+
+ while (channel->priv->current_job == NULL &&
+ channel->priv->queued_requests != NULL)
+ {
+ req = channel->priv->queued_requests->data;
+
+ channel->priv->queued_requests =
+ g_list_delete_link (channel->priv->queued_requests,
+ channel->priv->queued_requests);
+
+ error = NULL;
+ job = NULL;
+ if (req->cancelled)
+ {
+ error =
+ g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_free (req->data); /* Did no pass ownership */
+ }
+ else
+ {
+ /* This passes on ownership of req->data */
+ job = class->handle_request (channel,
+ req->command, req->seq_nr,
+ req->arg1, req->arg2,
+ req->data, req->data_len,
+ &error);
+ }
+
+ if (job)
+ {
+ channel->priv->current_job = job;
+ channel->priv->current_job_seq_nr = req->seq_nr;
+ g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (channel), channel->priv->current_job);
+ started_job = TRUE;
+ }
+ else
+ {
+ g_vfs_channel_send_error (channel, error);
+ g_error_free (error);
+ }
+
+ g_free (req);
+ }
+
+ return started_job;
+}
+
+
+/* Ownership of data is passed here to avoid copying it */
+static void
+got_request (GVfsChannel *channel,
+ GVfsDaemonSocketProtocolRequest *request,
+ gpointer data, gsize data_len)
+{
+ Request *req;
+ guint32 command, arg1;
+ GList *l;
+
+ command = g_ntohl (request->command);
+ arg1 = g_ntohl (request->arg1);
+
+ if (command == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL)
+ {
+ if (arg1 == channel->priv->current_job_seq_nr &&
+ channel->priv->current_job != NULL)
+ g_vfs_job_cancel (channel->priv->current_job);
+ else
+ {
+ for (l = channel->priv->queued_requests; l != NULL; l = l->next)
+ {
+ req = l->data;
+
+ if (req->seq_nr == 0)
+ /* We're cancelling something later but this readahead might
+ be the actual operation thats replacing it */
+ req->cancelled = TRUE;
+
+ if (req->seq_nr == arg1)
+ {
+ req->cancelled = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Cancel ops get no return */
+ g_free (data);
+ return;
+ }
+
+ req = g_new0 (Request, 1);
+ req->command = command;
+ req->arg1 = arg1;
+ req->arg2 = g_ntohl (request->arg2);
+ req->seq_nr = g_ntohl (request->seq_nr);
+ req->data_len = data_len;
+ req->data = data;
+
+ channel->priv->queued_requests =
+ g_list_append (channel->priv->queued_requests,
+ req);
+
+ start_queued_request (channel);
+}
+
+static void command_read_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+
+static void
+finish_request (RequestReader *reader)
+{
+ /* Ownership of reader->data passed here */
+ got_request (reader->channel, (GVfsDaemonSocketProtocolRequest *)reader->buffer,
+ reader->data, reader->data_len);
+ reader->data = NULL;
+
+ /* Request more commands immediately, so can get cancel requests */
+
+ reader->buffer_size = 0;
+ reader->data_len = 0;
+ g_input_stream_read_async (reader->command_stream,
+ reader->buffer + reader->buffer_size,
+ G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
+ 0, NULL,
+ command_read_cb,
+ reader);
+}
+
+static void
+data_read_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ RequestReader *reader = user_data;
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ gssize count_read;
+
+ if (reader->channel == NULL)
+ {
+ /* Channel was finalized */
+ request_reader_free (reader);
+ return;
+ }
+
+ count_read = g_input_stream_read_finish (stream, res, NULL);
+
+ if (count_read <= 0)
+ {
+ reader->channel->priv->request_reader = NULL;
+ g_vfs_channel_connection_closed (reader->channel);
+ request_reader_free (reader);
+ return;
+ }
+
+ reader->data_pos += count_read;
+
+ if (reader->data_pos < reader->data_len)
+ {
+ g_input_stream_read_async (reader->command_stream,
+ reader->data + reader->data_pos,
+ reader->data_len - reader->data_pos,
+ 0, NULL,
+ data_read_cb, reader);
+ return;
+ }
+
+ finish_request (reader);
+}
+
+
+static void
+command_read_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ RequestReader *reader = user_data;
+ GVfsDaemonSocketProtocolRequest *request;
+ guint32 data_len;
+ gssize count_read;
+
+ if (reader->channel == NULL)
+ {
+ /* Channel was finalized */
+ request_reader_free (reader);
+ return;
+ }
+
+ count_read = g_input_stream_read_finish (stream, res, NULL);
+
+ if (count_read <= 0)
+ {
+ reader->channel->priv->request_reader = NULL;
+ g_vfs_channel_connection_closed (reader->channel);
+ request_reader_free (reader);
+ return;
+ }
+
+ reader->buffer_size += count_read;
+
+ if (reader->buffer_size < G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE)
+ {
+ g_input_stream_read_async (reader->command_stream,
+ reader->buffer + reader->buffer_size,
+ G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
+ 0, NULL,
+ command_read_cb, reader);
+ return;
+ }
+
+ request = (GVfsDaemonSocketProtocolRequest *)reader->buffer;
+ data_len = g_ntohl (request->data_len);
+
+ if (data_len > 0)
+ {
+ reader->data = g_malloc (data_len);
+ reader->data_len = data_len;
+ reader->data_pos = 0;
+
+ g_input_stream_read_async (reader->command_stream,
+ reader->data + reader->data_pos,
+ reader->data_len - reader->data_pos,
+ 0, NULL,
+ data_read_cb, reader);
+ return;
+ }
+
+ finish_request (reader);
+}
+
+static void
+start_request_reader (GVfsChannel *channel)
+{
+ RequestReader *reader;
+
+ reader = g_new0 (RequestReader, 1);
+ reader->channel = channel;
+ reader->command_stream = g_object_ref (channel->priv->command_stream);
+
+ g_input_stream_read_async (reader->command_stream,
+ reader->buffer + reader->buffer_size,
+ G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE - reader->buffer_size,
+ 0, NULL,
+ command_read_cb, reader);
+
+ channel->priv->request_reader = reader;
+}
+
+static void
+send_reply_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GOutputStream *output_stream = G_OUTPUT_STREAM (source_object);
+ gssize bytes_written;
+ GVfsChannel *channel = user_data;
+ GVfsChannelClass *class;
+ GVfsJob *job;
+
+ bytes_written = g_output_stream_write_finish (output_stream, res, NULL);
+
+ if (bytes_written <= 0)
+ {
+ g_vfs_channel_connection_closed (channel);
+ goto error_out;
+ }
+
+ if (channel->priv->reply_buffer_pos < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE)
+ {
+ channel->priv->reply_buffer_pos += bytes_written;
+
+ /* Write more of reply header if needed */
+ if (channel->priv->reply_buffer_pos < G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE)
+ {
+ g_output_stream_write_async (channel->priv->reply_stream,
+ channel->priv->reply_buffer + channel->priv->reply_buffer_pos,
+ G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE - channel->priv->reply_buffer_pos,
+ 0, NULL,
+ send_reply_cb, channel);
+ return;
+ }
+ bytes_written = 0;
+ }
+
+ channel->priv->output_data_pos += bytes_written;
+
+ /* Write more of output_data if needed */
+ if (channel->priv->output_data != NULL &&
+ channel->priv->output_data_pos < channel->priv->output_data_size)
+ {
+ g_output_stream_write_async (channel->priv->reply_stream,
+ channel->priv->output_data + channel->priv->output_data_pos,
+ channel->priv->output_data_size - channel->priv->output_data_pos,
+ 0, NULL,
+ send_reply_cb, channel);
+ return;
+ }
+
+ error_out:
+
+ /* Sent full reply */
+ channel->priv->output_data = NULL;
+
+ job = channel->priv->current_job;
+ channel->priv->current_job = NULL;
+ g_vfs_job_emit_finished (job);
+
+ class = G_VFS_CHANNEL_GET_CLASS (channel);
+
+ if (G_VFS_IS_JOB_CLOSE_READ (job) ||
+ G_VFS_IS_JOB_CLOSE_WRITE (job))
+ {
+ g_vfs_job_source_closed (G_VFS_JOB_SOURCE (channel));
+ channel->priv->backend_handle = NULL;
+ }
+ else if (channel->priv->connection_closed)
+ {
+
+ channel->priv->current_job = class->close (channel);
+ channel->priv->current_job_seq_nr = 0;
+ g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (channel), channel->priv->current_job);
+ }
+ /* Start queued request or readahead */
+ else if (!start_queued_request (channel) &&
+ class->readahead)
+ {
+ /* No queued requests, maybe we want to do a readahead call */
+ channel->priv->current_job = class->readahead (channel, job);
+ channel->priv->current_job_seq_nr = 0;
+ if (channel->priv->current_job)
+ g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (channel), channel->priv->current_job);
+ }
+
+ g_object_unref (job);
+}
+
+/* Might be called on an i/o thread */
+void
+g_vfs_channel_send_reply (GVfsChannel *channel,
+ GVfsDaemonSocketProtocolReply *reply,
+ const void *data,
+ gsize data_len)
+{
+
+ channel->priv->output_data = data;
+ channel->priv->output_data_size = data_len;
+ channel->priv->output_data_pos = 0;
+
+ if (reply != NULL)
+ {
+ memcpy (channel->priv->reply_buffer, reply, sizeof (GVfsDaemonSocketProtocolReply));
+ channel->priv->reply_buffer_pos = 0;
+
+ g_output_stream_write_async (channel->priv->reply_stream,
+ channel->priv->reply_buffer,
+ G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE,
+ 0, NULL,
+ send_reply_cb, channel);
+ }
+ else
+ {
+ channel->priv->reply_buffer_pos = G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE;
+ g_output_stream_write_async (channel->priv->reply_stream,
+ channel->priv->output_data,
+ channel->priv->output_data_size,
+ 0, NULL,
+ send_reply_cb, channel);
+ }
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_channel_send_error (GVfsChannel *channel,
+ GError *error)
+{
+ char *data;
+ gsize data_len;
+
+ data = g_error_to_daemon_reply (error, channel->priv->current_job_seq_nr, &data_len);
+ g_vfs_channel_send_reply (channel, NULL, data, data_len);
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_channel_send_info (GVfsChannel *channel,
+ GFileInfo *info)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ char *data;
+ gsize data_len;
+
+ data = gvfs_file_info_marshal (info, &data_len);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_INFO);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = 0;
+ reply.arg2 = g_htonl (data_len);
+
+ g_vfs_channel_send_reply (channel, &reply, data, data_len);
+}
+
+int
+g_vfs_channel_steal_remote_fd (GVfsChannel *channel)
+{
+ int fd;
+ fd = channel->priv->remote_fd;
+ channel->priv->remote_fd = -1;
+ return fd;
+}
+
+GVfsBackend *
+g_vfs_channel_get_backend (GVfsChannel *channel)
+{
+ return channel->priv->backend;
+}
+
+void
+g_vfs_channel_set_backend_handle (GVfsChannel *channel,
+ GVfsBackendHandle backend_handle)
+{
+ channel->priv->backend_handle = backend_handle;
+}
+
+GVfsBackendHandle
+g_vfs_channel_get_backend_handle (GVfsChannel *channel)
+{
+ return channel->priv->backend_handle;
+}
+
+guint32
+g_vfs_channel_get_current_seq_nr (GVfsChannel *channel)
+{
+ return channel->priv->current_job_seq_nr;
+}
diff --git a/trunk/daemon/gvfschannel.h b/trunk/daemon/gvfschannel.h
new file mode 100644
index 00000000..0dc92fce
--- /dev/null
+++ b/trunk/daemon/gvfschannel.h
@@ -0,0 +1,91 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_CHANNEL_H__
+#define __G_VFS_CHANNEL_H__
+
+#include <glib-object.h>
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfsdaemonprotocol.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_CHANNEL (g_vfs_channel_get_type ())
+#define G_VFS_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_CHANNEL, GVfsChannel))
+#define G_VFS_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_CHANNEL, GVfsChannelClass))
+#define G_VFS_IS_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_CHANNEL))
+#define G_VFS_IS_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_CHANNEL))
+#define G_VFS_CHANNEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_CHANNEL, GVfsChannelClass))
+
+typedef struct _GVfsChannel GVfsChannel;
+typedef struct _GVfsChannelClass GVfsChannelClass;
+typedef struct _GVfsChannelPrivate GVfsChannelPrivate;
+
+struct _GVfsChannel
+{
+ GObject parent_instance;
+
+ GVfsChannelPrivate *priv;
+};
+
+struct _GVfsChannelClass
+{
+ GObjectClass parent_class;
+
+ GVfsJob *(*close) (GVfsChannel *channel);
+ GVfsJob *(*handle_request) (GVfsChannel *channel,
+ guint32 command,
+ guint32 seq_nr,
+ guint32 arg1,
+ guint32 arg2,
+ gpointer data,
+ gsize data_len,
+ GError **error);
+ GVfsJob *(*readahead) (GVfsChannel *channel,
+ GVfsJob *job);
+};
+
+GType g_vfs_channel_get_type (void) G_GNUC_CONST;
+
+int g_vfs_channel_steal_remote_fd (GVfsChannel *channel);
+GVfsBackend * g_vfs_channel_get_backend (GVfsChannel *channel);
+GVfsBackendHandle g_vfs_channel_get_backend_handle (GVfsChannel *channel);
+void g_vfs_channel_set_backend_handle (GVfsChannel *channel,
+ GVfsBackendHandle backend_handle);
+gboolean g_vfs_channel_has_job (GVfsChannel *channel);
+GVfsJob * g_vfs_channel_get_job (GVfsChannel *channel);
+void g_vfs_channel_send_error (GVfsChannel *channel,
+ GError *error);
+void g_vfs_channel_send_info (GVfsChannel *channel,
+ GFileInfo *info);
+void g_vfs_channel_send_reply (GVfsChannel *channel,
+ GVfsDaemonSocketProtocolReply *reply,
+ const void *data,
+ gsize data_len);
+guint32 g_vfs_channel_get_current_seq_nr (GVfsChannel *channel);
+
+/* TODO: i/o priority? */
+
+G_END_DECLS
+
+#endif /* __G_VFS_CHANNEL_H__ */
diff --git a/trunk/daemon/gvfsdaemon.c b/trunk/daemon/gvfsdaemon.c
new file mode 100644
index 00000000..57a4edbe
--- /dev/null
+++ b/trunk/daemon/gvfsdaemon.c
@@ -0,0 +1,1060 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <errno.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#include <dbus-gmain.h>
+#include <gvfsdaemon.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsdaemonutils.h>
+#include <gvfsjobmount.h>
+#include <gdbusutils.h>
+
+enum {
+ PROP_0
+};
+
+typedef struct {
+ char *obj_path;
+ DBusObjectPathMessageFunction callback;
+ gpointer data;
+} RegisteredPath;
+
+struct _GVfsDaemon
+{
+ GObject parent_instance;
+
+ GMutex *lock;
+ gboolean main_daemon;
+
+ GThreadPool *thread_pool;
+ DBusConnection *session_bus;
+ GHashTable *registered_paths;
+ GList *jobs;
+ GList *job_sources;
+
+ guint exit_tag;
+
+ gint mount_counter;
+};
+
+typedef struct {
+ GVfsDaemon *daemon;
+ char *socket_dir;
+ guint io_watch;
+ DBusServer *server;
+
+ gboolean got_dbus_connection;
+ gboolean got_fd_connection;
+ int fd;
+ DBusConnection *conn;
+} NewConnectionData;
+
+static void g_vfs_daemon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void g_vfs_daemon_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static DBusHandlerResult daemon_message_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data);
+static DBusHandlerResult peer_to_peer_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data);
+
+
+G_DEFINE_TYPE (GVfsDaemon, g_vfs_daemon, G_TYPE_OBJECT)
+
+static void
+registered_path_free (RegisteredPath *data)
+{
+ g_free (data->obj_path);
+ g_free (data);
+}
+
+static void
+g_vfs_daemon_finalize (GObject *object)
+{
+ GVfsDaemon *daemon;
+
+ daemon = G_VFS_DAEMON (object);
+
+ g_assert (daemon->jobs == NULL);
+
+ g_hash_table_destroy (daemon->registered_paths);
+ g_mutex_free (daemon->lock);
+
+ if (G_OBJECT_CLASS (g_vfs_daemon_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_daemon_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_daemon_class_init (GVfsDaemonClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_daemon_finalize;
+ gobject_class->set_property = g_vfs_daemon_set_property;
+ gobject_class->get_property = g_vfs_daemon_get_property;
+}
+
+static void
+job_handler_callback (gpointer data,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (data);
+
+ g_vfs_job_run (job);
+}
+
+static void
+g_vfs_daemon_init (GVfsDaemon *daemon)
+{
+ gint max_threads = 1; /* TODO: handle max threads */
+ DBusError error;
+
+ daemon->lock = g_mutex_new ();
+ daemon->session_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ daemon->thread_pool = g_thread_pool_new (job_handler_callback,
+ daemon,
+ max_threads,
+ FALSE, NULL);
+ /* TODO: verify thread_pool != NULL in a nicer way */
+ g_assert (daemon->thread_pool != NULL);
+
+ daemon->mount_counter = 0;
+
+ daemon->jobs = NULL;
+ daemon->registered_paths =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify)registered_path_free);
+
+ dbus_error_init (&error);
+ dbus_bus_add_match (daemon->session_bus,
+ "type='signal',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',"
+ "arg0='"G_VFS_DBUS_DAEMON_NAME"'",
+ &error);
+
+ if (dbus_error_is_set (&error))
+ {
+ g_warning ("Failed to add dbus match: %s\n", error.message);
+ dbus_error_free (&error);
+ }
+
+ if (!dbus_connection_add_filter (daemon->session_bus,
+ daemon_message_func, daemon, NULL))
+ _g_dbus_oom ();
+}
+
+static void
+g_vfs_daemon_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+#if 0
+ GVfsDaemon *daemon;
+
+ daemon = G_VFS_DAEMON (object);
+#endif
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_daemon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+#if 0
+ GVfsDaemon *daemon;
+
+ daemon = G_VFS_DAEMON (object);
+#endif
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+GVfsDaemon *
+g_vfs_daemon_new (gboolean main_daemon, gboolean replace)
+{
+ GVfsDaemon *daemon;
+ DBusConnection *conn;
+ DBusError error;
+ unsigned int flags;
+ int ret;
+
+ dbus_error_init (&error);
+ conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ if (!conn)
+ {
+ g_printerr ("Failed to connect to the D-BUS daemon: %s\n",
+ error.message);
+
+ dbus_error_free (&error);
+ return NULL;
+ }
+
+ dbus_connection_setup_with_g_main (conn, NULL);
+
+ daemon = g_object_new (G_VFS_TYPE_DAEMON, NULL);
+ daemon->main_daemon = main_daemon;
+
+ /* Request name only after we've installed the message filter */
+ if (main_daemon)
+ {
+ flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT | DBUS_NAME_FLAG_DO_NOT_QUEUE;
+ if (replace)
+ flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
+
+ ret = dbus_bus_request_name (conn, G_VFS_DBUS_DAEMON_NAME, flags, &error);
+ if (ret == -1)
+ {
+ g_printerr ("Failed to acquire daemon name: %s", error.message);
+ dbus_error_free (&error);
+
+ g_object_unref (daemon);
+ daemon = NULL;
+ }
+ else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
+ {
+ g_printerr ("VFS daemon already running, exiting.\n");
+ g_object_unref (daemon);
+ daemon = NULL;
+ }
+ else if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ g_printerr ("Not primary owner of the service, exiting.\n");
+ g_object_unref (daemon);
+ daemon = NULL;
+ }
+ }
+
+ dbus_connection_unref (conn);
+
+ return daemon;
+}
+
+void
+g_vfs_daemon_set_max_threads (GVfsDaemon *daemon,
+ gint max_threads)
+{
+ g_thread_pool_set_max_threads (daemon->thread_pool, max_threads, NULL);
+}
+
+static gboolean
+exit_at_idle (gpointer data)
+{
+ exit (0);
+ return FALSE;
+}
+
+static void
+daemon_unschedule_exit (GVfsDaemon *daemon)
+{
+ if (daemon->exit_tag != 0)
+ {
+ g_source_remove (daemon->exit_tag);
+ daemon->exit_tag = 0;
+ }
+}
+
+static void
+daemon_schedule_exit (GVfsDaemon *daemon)
+{
+ if (daemon->exit_tag == 0)
+ daemon->exit_tag = g_timeout_add_seconds (1, exit_at_idle, daemon);
+}
+
+static void
+job_source_new_job_callback (GVfsJobSource *job_source,
+ GVfsJob *job,
+ GVfsDaemon *daemon)
+{
+ g_vfs_daemon_queue_job (daemon, job);
+}
+
+static void
+job_source_closed_callback (GVfsJobSource *job_source,
+ GVfsDaemon *daemon)
+{
+ g_mutex_lock (daemon->lock);
+
+ daemon->job_sources = g_list_remove (daemon->job_sources,
+ job_source);
+
+ g_signal_handlers_disconnect_by_func (job_source,
+ (GCallback)job_source_new_job_callback,
+ daemon);
+ g_signal_handlers_disconnect_by_func (job_source,
+ (GCallback)job_source_closed_callback,
+ daemon);
+
+ g_object_unref (job_source);
+
+ if (daemon->job_sources == NULL)
+ daemon_schedule_exit (daemon);
+
+ g_mutex_unlock (daemon->lock);
+}
+
+static void
+g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon)
+{
+ GList *l;
+
+ g_mutex_lock (daemon->lock);
+
+ for (l = daemon->job_sources; l != NULL; l = l->next)
+ {
+ if (G_VFS_IS_BACKEND (l->data))
+ g_vfs_backend_register_mount (l->data, NULL, NULL);
+ }
+
+ g_mutex_unlock (daemon->lock);
+}
+
+void
+g_vfs_daemon_add_job_source (GVfsDaemon *daemon,
+ GVfsJobSource *job_source)
+{
+ g_debug ("Added new job source %p (%s)\n", job_source, g_type_name_from_instance ((gpointer)job_source));
+
+ g_mutex_lock (daemon->lock);
+
+ daemon_unschedule_exit (daemon);
+
+ g_object_ref (job_source);
+ daemon->job_sources = g_list_append (daemon->job_sources,
+ job_source);
+ g_signal_connect (job_source, "new_job",
+ (GCallback)job_source_new_job_callback, daemon);
+ g_signal_connect (job_source, "closed",
+ (GCallback)job_source_closed_callback, daemon);
+
+ g_mutex_unlock (daemon->lock);
+}
+
+/* This registers a dbus callback on *all* connections, client and session bus */
+void
+g_vfs_daemon_register_path (GVfsDaemon *daemon,
+ const char *obj_path,
+ DBusObjectPathMessageFunction callback,
+ gpointer user_data)
+{
+ RegisteredPath *data;
+
+ data = g_new0 (RegisteredPath, 1);
+ data->obj_path = g_strdup (obj_path);
+ data->callback = callback;
+ data->data = user_data;
+
+ g_hash_table_insert (daemon->registered_paths, data->obj_path,
+ data);
+}
+
+void
+g_vfs_daemon_unregister_path (GVfsDaemon *daemon,
+ const char *obj_path)
+{
+ g_hash_table_remove (daemon->registered_paths, obj_path);
+}
+
+/* NOTE: Might be emitted on a thread */
+static void
+job_new_source_callback (GVfsJob *job,
+ GVfsJobSource *job_source,
+ GVfsDaemon *daemon)
+{
+ g_vfs_daemon_add_job_source (daemon, job_source);
+}
+
+/* NOTE: Might be emitted on a thread */
+static void
+job_finished_callback (GVfsJob *job,
+ GVfsDaemon *daemon)
+{
+
+ g_signal_handlers_disconnect_by_func (job,
+ (GCallback)job_new_source_callback,
+ daemon);
+ g_signal_handlers_disconnect_by_func (job,
+ (GCallback)job_finished_callback,
+ daemon);
+
+ g_mutex_lock (daemon->lock);
+ daemon->jobs = g_list_remove (daemon->jobs, job);
+ g_mutex_unlock (daemon->lock);
+
+ g_object_unref (job);
+}
+
+void
+g_vfs_daemon_queue_job (GVfsDaemon *daemon,
+ GVfsJob *job)
+{
+ g_debug ("Queued new job %p (%s)\n", job, g_type_name_from_instance ((gpointer)job));
+
+ g_object_ref (job);
+ g_signal_connect (job, "finished", (GCallback)job_finished_callback, daemon);
+ g_signal_connect (job, "new_source", (GCallback)job_new_source_callback, daemon);
+
+ g_mutex_lock (daemon->lock);
+ daemon->jobs = g_list_prepend (daemon->jobs, job);
+ g_mutex_unlock (daemon->lock);
+
+ /* Can we start the job immediately / async */
+ if (!g_vfs_job_try (job))
+ {
+ /* Couldn't finish / run async, queue worker thread */
+ g_thread_pool_push (daemon->thread_pool, job, NULL); /* TODO: Check error */
+ }
+}
+
+static void
+new_connection_data_free (void *memory)
+{
+ NewConnectionData *data = memory;
+
+ /* Remove the socket and dir after connected */
+ if (data->socket_dir)
+ rmdir (data->socket_dir);
+
+ if (data->io_watch)
+ g_source_remove (data->io_watch);
+
+ g_free (data->socket_dir);
+ g_free (data);
+}
+
+static void
+daemon_peer_connection_setup (GVfsDaemon *daemon,
+ DBusConnection *dbus_conn,
+ NewConnectionData *data)
+{
+ /* We wait until we have the extra fd */
+ if (!data->got_fd_connection)
+ return;
+
+ if (data->fd == -1)
+ {
+ /* The fd connection failed, abort the whole thing */
+ g_warning ("Failed to accept client: %s", "accept of extra fd failed");
+ dbus_connection_unref (dbus_conn);
+ goto error_out;
+ }
+
+ dbus_connection_setup_with_g_main (dbus_conn, NULL);
+ if (!dbus_connection_add_filter (dbus_conn, peer_to_peer_filter_func, daemon, NULL) ||
+ !dbus_connection_add_filter (dbus_conn, daemon_message_func, daemon, NULL))
+ {
+ g_warning ("Failed to accept client: %s", "object registration failed");
+ dbus_connection_unref (dbus_conn);
+ close (data->fd);
+ goto error_out;
+ }
+
+ dbus_connection_add_fd_send_fd (dbus_conn, data->fd);
+
+ error_out:
+ new_connection_data_free (data);
+}
+
+#ifdef __linux__
+#define USE_ABSTRACT_SOCKETS
+#endif
+
+static void
+randomize_string (char tmp[9])
+{
+ int i;
+ const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ for (i = 0; i < 8; i++)
+ tmp[i] = chars[g_random_int_range (0, strlen(chars))];
+
+ tmp[8] = '\0';
+}
+
+#ifndef USE_ABSTRACT_SOCKETS
+static gboolean
+test_safe_socket_dir (const char *dirname)
+{
+ struct stat statbuf;
+
+ if (g_stat (dirname, &statbuf) != 0)
+ return FALSE;
+
+#ifndef G_PLATFORM_WIN32
+ if (statbuf.st_uid != getuid ())
+ return FALSE;
+
+ if ((statbuf.st_mode & (S_IRWXG|S_IRWXO)) ||
+ !S_ISDIR (statbuf.st_mode))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+
+static char *
+create_socket_dir (void)
+{
+ char *dirname;
+ long iteration = 0;
+ char *safe_dir;
+ gchar tmp[9];
+ int i;
+
+ safe_dir = NULL;
+ do
+ {
+ g_free (safe_dir);
+
+ randomize_string (tmp);
+
+ dirname = g_strdup_printf ("gvfs-%s-%s",
+ g_get_user_name (), tmp);
+ safe_dir = g_build_filename (g_get_tmp_dir (), dirname, NULL);
+ g_free (dirname);
+
+ if (g_mkdir (safe_dir, 0700) < 0)
+ {
+ switch (errno)
+ {
+ case EACCES:
+ g_error ("I can't write to '%s', daemon init failed",
+ safe_dir);
+ break;
+
+ case ENAMETOOLONG:
+ g_error ("Name '%s' too long your system is broken",
+ safe_dir);
+ break;
+
+ case ENOMEM:
+#ifdef ELOOP
+ case ELOOP:
+#endif
+ case ENOSPC:
+ case ENOTDIR:
+ case ENOENT:
+ g_error ("Resource problem creating '%s'", safe_dir);
+ break;
+
+ default: /* carry on going */
+ break;
+ }
+ }
+ /* Possible race - so we re-scan. */
+
+ if (iteration++ == 1000)
+ g_error ("Cannot find a safe socket path in '%s'", g_get_tmp_dir ());
+ }
+ while (!test_safe_socket_dir (safe_dir));
+
+ return safe_dir;
+}
+#endif
+
+static void
+generate_addresses (char **address1,
+ char **address2,
+ char **folder)
+{
+ *address1 = NULL;
+ *address2 = NULL;
+ *folder = NULL;
+
+#ifdef USE_ABSTRACT_SOCKETS
+ {
+ gchar tmp[9];
+
+ randomize_string (tmp);
+ *address1 = g_strdup_printf ("unix:abstract=/dbus-vfs-daemon/socket-%s", tmp);
+
+ randomize_string (tmp);
+ *address2 = g_strdup_printf ("unix:abstract=/dbus-vfs-daemon/socket-%s", tmp);
+ }
+#else
+ {
+ char *dir;
+
+ dir = create_socket_dir ();
+ *address1 = g_strdup_printf ("unix:path=%s/socket1", dir);
+ *address2 = g_strdup_printf ("unix:path=%s/socket2", dir);
+ *folder = dir;
+ }
+#endif
+}
+
+static void
+daemon_new_connection_func (DBusServer *server,
+ DBusConnection *conn,
+ gpointer user_data)
+{
+ NewConnectionData *data;
+
+ data = user_data;
+ data->got_dbus_connection = TRUE;
+
+ /* Take ownership */
+ data->conn = dbus_connection_ref (conn);
+
+ daemon_peer_connection_setup (data->daemon, conn, data);
+
+ /* Kill the server, no more need for it */
+ dbus_server_disconnect (server);
+ dbus_server_unref (server);
+}
+
+static int
+unix_socket_at (const char *address)
+{
+ int fd;
+ const char *path;
+ size_t path_len;
+ struct sockaddr_un addr;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ return -1;
+
+#ifdef USE_ABSTRACT_SOCKETS
+ path = address + strlen ("unix:abstract=");
+#else
+ path = address + strlen ("unix:path=");
+#endif
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ path_len = strlen (path);
+
+#ifdef USE_ABSTRACT_SOCKETS
+ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+ path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+ strncpy (&addr.sun_path[1], path, path_len);
+#else /* USE_ABSTRACT_SOCKETS */
+ strncpy (addr.sun_path, path, path_len);
+ unlink (path);
+#endif /* ! USE_ABSTRACT_SOCKETS */
+
+ if (bind (fd, (struct sockaddr*) &addr,
+ G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+ {
+ close (fd);
+ return -1;
+ }
+
+ if (listen (fd, 30 /* backlog */) < 0)
+ {
+ close (fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static gboolean
+accept_new_fd_client (GIOChannel *channel,
+ GIOCondition cond,
+ gpointer callback_data)
+{
+ NewConnectionData *data = callback_data;
+ int fd;
+ int new_fd;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+
+ data->got_fd_connection = TRUE;
+
+ fd = g_io_channel_unix_get_fd (channel);
+
+ addrlen = sizeof (addr);
+ new_fd = accept (fd, (struct sockaddr *) &addr, &addrlen);
+
+ data->fd = new_fd;
+ data->io_watch = 0;
+
+ /* Did we already accept the dbus connection, if so, finish it now */
+ if (data->got_dbus_connection)
+ daemon_peer_connection_setup (data->daemon,
+ data->conn,
+ data);
+ else if (data->fd == -1)
+ {
+ /* Didn't accept a dbus connection, and there is no need for one now */
+ g_warning ("Failed to accept client: %s", "accept of extra fd failed");
+ dbus_server_disconnect (data->server);
+ dbus_server_unref (data->server);
+ new_connection_data_free (data);
+ }
+
+ return FALSE;
+}
+
+static void
+daemon_handle_get_connection (DBusConnection *conn,
+ DBusMessage *message,
+ GVfsDaemon *daemon)
+{
+ DBusServer *server;
+ DBusError error;
+ DBusMessage *reply;
+ gchar *address1;
+ gchar *address2;
+ NewConnectionData *data;
+ GIOChannel *channel;
+ char *socket_dir;
+ int fd;
+
+ generate_addresses (&address1, &address2, &socket_dir);
+
+ data = g_new (NewConnectionData, 1);
+ data->daemon = daemon;
+ data->socket_dir = socket_dir;
+ data->got_fd_connection = FALSE;
+ data->got_dbus_connection = FALSE;
+ data->fd = -1;
+ data->conn = NULL;
+
+ dbus_error_init (&error);
+ server = dbus_server_listen (address1, &error);
+ if (!server)
+ {
+ reply = dbus_message_new_error_printf (message,
+ G_VFS_DBUS_ERROR_SOCKET_FAILED,
+ "Failed to create new socket: %s",
+ error.message);
+ dbus_error_free (&error);
+ if (reply)
+ {
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+ }
+
+ goto error_out;
+ }
+ data->server = server;
+
+ dbus_server_set_new_connection_function (server,
+ daemon_new_connection_func,
+ data, NULL);
+ dbus_server_setup_with_g_main (server, NULL);
+
+ fd = unix_socket_at (address2);
+ if (fd == -1)
+ goto error_out;
+
+ channel = g_io_channel_unix_new (fd);
+ g_io_channel_set_close_on_unref (channel, TRUE);
+ data->io_watch = g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_new_fd_client, data);
+ g_io_channel_unref (channel);
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ if (!dbus_message_append_args (reply,
+ DBUS_TYPE_STRING, &address1,
+ DBUS_TYPE_STRING, &address2,
+ DBUS_TYPE_INVALID))
+ _g_dbus_oom ();
+
+ dbus_connection_send (conn, reply, NULL);
+
+ dbus_message_unref (reply);
+
+ g_free (address1);
+ g_free (address2);
+
+ return;
+
+ error_out:
+ g_free (data);
+ g_free (address1);
+ g_free (address2);
+ if (socket_dir)
+ {
+ rmdir (socket_dir);
+ g_free (socket_dir);
+ }
+}
+
+static void
+daemon_start_mount (GVfsDaemon *daemon,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ const char *dbus_id, *obj_path;
+ DBusMessageIter iter;
+ DBusError derror;
+ DBusMessage *reply;
+ GMountSpec *mount_spec;
+ GMountSource *mount_source;
+ dbus_bool_t automount;
+
+ dbus_message_iter_init (message, &iter);
+
+ reply = NULL;
+ mount_spec = NULL;
+ dbus_error_init (&derror);
+ if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL)
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Error in mount spec");
+ else if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ DBUS_TYPE_BOOLEAN, &automount,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message, derror.name, derror.message);
+ dbus_error_free (&derror);
+ }
+
+ if (reply)
+ {
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ }
+ else
+ {
+ mount_source = g_mount_source_new (dbus_id, obj_path);
+ g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, automount, message);
+ g_object_unref (mount_source);
+ g_mount_spec_unref (mount_spec);
+ }
+}
+
+static DBusHandlerResult
+daemon_message_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ GVfsDaemon *daemon = data;
+ RegisteredPath *registered_path;
+ const char *path;
+ char *name;
+ char *old_owner, *new_owner;
+
+ path = dbus_message_get_path (message);
+ if (path == NULL)
+ path = "";
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameLost"))
+ {
+ if (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID) &&
+ strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0)
+ {
+ /* Someone else got the name (i.e. someone used --replace), exit */
+ if (daemon->main_daemon)
+ exit (1);
+ }
+ }
+ else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+ {
+ if (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old_owner,
+ DBUS_TYPE_STRING, &new_owner,
+ DBUS_TYPE_INVALID) &&
+ strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0 &&
+ *new_owner != 0 &&
+ !daemon->main_daemon)
+ {
+ /* There is a new owner. Register mounts with it */
+ g_vfs_daemon_re_register_job_sources (daemon);
+ }
+
+ }
+
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_GET_CONNECTION))
+ {
+ daemon_handle_get_connection (conn, message, daemon);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_DAEMON_INTERFACE,
+ G_VFS_DBUS_OP_CANCEL))
+ {
+ GList *l;
+ dbus_uint32_t serial;
+ GVfsJob *job_to_cancel = NULL;
+
+ if (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_UINT32, &serial,
+ DBUS_TYPE_INVALID))
+ {
+ g_mutex_lock (daemon->lock);
+ for (l = daemon->jobs; l != NULL; l = l->next)
+ {
+ GVfsJob *job = l->data;
+
+ if (G_VFS_IS_JOB_DBUS (job) &&
+ g_vfs_job_dbus_is_serial (G_VFS_JOB_DBUS (job),
+ conn, serial))
+ {
+ job_to_cancel = g_object_ref (job);
+ break;
+ }
+ }
+ g_mutex_unlock (daemon->lock);
+
+
+ if (job_to_cancel)
+ {
+ g_vfs_job_cancel (job_to_cancel);
+ g_object_unref (job_to_cancel);
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (strcmp (path, G_VFS_DBUS_MOUNTABLE_PATH) == 0 &&
+ dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTABLE_INTERFACE,
+ G_VFS_DBUS_MOUNTABLE_OP_MOUNT))
+ {
+ daemon_start_mount (daemon, conn, message);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ registered_path = g_hash_table_lookup (daemon->registered_paths, path);
+
+ if (registered_path)
+ return registered_path->callback (conn, message, registered_path->data);
+ else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+/* Only called for peer-to-peer connections */
+static DBusHandlerResult
+peer_to_peer_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected"))
+ {
+ /* The peer-to-peer connection was disconnected */
+ dbus_connection_unref (conn);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+void
+g_vfs_daemon_initiate_mount (GVfsDaemon *daemon,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount,
+ DBusMessage *request)
+{
+ const char *type;
+ GType backend_type;
+ char *obj_path;
+ GVfsJob *job;
+ GVfsBackend *backend;
+ DBusConnection *conn;
+ DBusMessage *reply;
+
+ type = g_mount_spec_get_type (mount_spec);
+
+ backend_type = G_TYPE_INVALID;
+ if (type)
+ backend_type = g_vfs_lookup_backend (type);
+
+ if (backend_type == G_TYPE_INVALID)
+ {
+ if (request)
+ {
+ reply = _dbus_message_new_gerror (request,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid backend type"));
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+ dbus_connection_unref (conn);
+ }
+ }
+ else
+ g_warning ("Error mounting: invalid backend type\n");
+ return;
+ }
+
+ obj_path = g_strdup_printf ("/org/gtk/vfs/mount/%d", ++daemon->mount_counter);
+ backend = g_object_new (backend_type,
+ "daemon", daemon,
+ "object_path", obj_path,
+ NULL);
+ g_free (obj_path);
+
+ g_vfs_daemon_add_job_source (daemon, G_VFS_JOB_SOURCE (backend));
+ g_object_unref (backend);
+
+ job = g_vfs_job_mount_new (mount_spec, mount_source, is_automount, request, backend);
+ g_vfs_daemon_queue_job (daemon, job);
+}
diff --git a/trunk/daemon/gvfsdaemon.h b/trunk/daemon/gvfsdaemon.h
new file mode 100644
index 00000000..f40f2166
--- /dev/null
+++ b/trunk/daemon/gvfsdaemon.h
@@ -0,0 +1,76 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_DAEMON_H__
+#define __G_VFS_DAEMON_H__
+
+#include <glib-object.h>
+#include <gvfsjobsource.h>
+#include <gmountsource.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_DAEMON (g_vfs_daemon_get_type ())
+#define G_VFS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_DAEMON, GVfsDaemon))
+#define G_VFS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_DAEMON, GVfsDaemonClass))
+#define G_VFS_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_DAEMON))
+#define G_VFS_IS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_DAEMON))
+#define G_VFS_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_DAEMON, GVfsDaemonClass))
+
+typedef struct _GVfsDaemon GVfsDaemon;
+typedef struct _GVfsDaemonClass GVfsDaemonClass;
+typedef struct _GVfsDaemonPrivate GVfsDaemonPrivate;
+
+struct _GVfsDaemonClass
+{
+ GObjectClass parent_class;
+
+ /* vtable */
+
+};
+
+GType g_vfs_daemon_get_type (void) G_GNUC_CONST;
+
+GVfsDaemon *g_vfs_daemon_new (gboolean main_daemon,
+ gboolean replace);
+void g_vfs_daemon_set_max_threads (GVfsDaemon *daemon,
+ gint max_threads);
+void g_vfs_daemon_add_job_source (GVfsDaemon *daemon,
+ GVfsJobSource *job_source);
+void g_vfs_daemon_queue_job (GVfsDaemon *daemon,
+ GVfsJob *job);
+void g_vfs_daemon_register_path (GVfsDaemon *daemon,
+ const char *obj_path,
+ DBusObjectPathMessageFunction callback,
+ gpointer user_data);
+void g_vfs_daemon_unregister_path (GVfsDaemon *daemon,
+ const char *obj_path);
+void g_vfs_daemon_initiate_mount (GVfsDaemon *daemon,
+ GMountSpec *mount_spec,
+ GMountSource *mount_source,
+ gboolean is_automount,
+ DBusMessage *request);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DAEMON_H__ */
diff --git a/trunk/daemon/gvfsdaemonutils.c b/trunk/daemon/gvfsdaemonutils.c
new file mode 100644
index 00000000..b221fdb8
--- /dev/null
+++ b/trunk/daemon/gvfsdaemonutils.c
@@ -0,0 +1,286 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gio/gio.h>
+#include "gdbusutils.h"
+#include "gsysutils.h"
+#include "gvfsdaemonutils.h"
+#include "gvfsdaemonprotocol.h"
+
+static gint32 extra_fd_slot = -1;
+static GStaticMutex extra_lock = G_STATIC_MUTEX_INIT;
+
+typedef struct {
+ int extra_fd;
+ int fd_count;
+} ConnectionExtra;
+
+static void
+free_extra (gpointer p)
+{
+ ConnectionExtra *extra = p;
+ close (extra->extra_fd);
+ g_free (extra);
+}
+
+void
+dbus_connection_add_fd_send_fd (DBusConnection *connection,
+ int extra_fd)
+{
+ ConnectionExtra *extra;
+
+ if (extra_fd_slot == -1 &&
+ !dbus_connection_allocate_data_slot (&extra_fd_slot))
+ g_error ("Unable to allocate data slot");
+
+ extra = g_new0 (ConnectionExtra, 1);
+ extra->extra_fd = extra_fd;
+
+ if (!dbus_connection_set_data (connection, extra_fd_slot, extra, free_extra))
+ _g_dbus_oom ();
+}
+
+gboolean
+dbus_connection_send_fd (DBusConnection *connection,
+ int fd,
+ int *fd_id,
+ GError **error)
+{
+ ConnectionExtra *extra;
+
+ g_assert (extra_fd_slot != -1);
+ extra = dbus_connection_get_data (connection, extra_fd_slot);
+ g_assert (extra != NULL);
+
+ if (extra->extra_fd == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Internal Error (%s)"), "No fd passing socket available");
+ return FALSE;
+ }
+
+ g_static_mutex_lock (&extra_lock);
+
+ if (_g_socket_send_fd (extra->extra_fd, fd) == -1)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error sending fd: %s"),
+ g_strerror (errsv));
+ g_static_mutex_unlock (&extra_lock);
+ return FALSE;
+ }
+
+ *fd_id = extra->fd_count++;
+
+ g_static_mutex_unlock (&extra_lock);
+
+ return TRUE;
+}
+
+char *
+g_error_to_daemon_reply (GError *error, guint32 seq_nr, gsize *len_out)
+{
+ char *buffer;
+ const char *domain;
+ gsize domain_len, message_len;
+ GVfsDaemonSocketProtocolReply *reply;
+ gsize len;
+
+ domain = g_quark_to_string (error->domain);
+ domain_len = strlen (domain);
+ message_len = strlen (error->message);
+
+ len = G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE +
+ domain_len + 1 + message_len + 1;
+ buffer = g_malloc (len);
+
+ reply = (GVfsDaemonSocketProtocolReply *)buffer;
+ reply->type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR);
+ reply->seq_nr = g_htonl (seq_nr);
+ reply->arg1 = g_htonl (error->code);
+ reply->arg2 = g_htonl (domain_len + 1 + message_len + 1);
+
+ memcpy (buffer + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE,
+ domain, domain_len + 1);
+ memcpy (buffer + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + domain_len + 1,
+ error->message, message_len + 1);
+
+ *len_out = len;
+
+ return buffer;
+}
+
+/**
+ * gvfs_file_info_populate_default:
+ * @info: file info to populate
+ * @name_string: a bytes string of possibly the full path to the given file
+ * @type: type of this file
+ *
+ * Calls gvfs_file_info_populate_names_as_local() and
+ * gvfs_file_info_populate_content_types() on the given @name_string.
+ **/
+void
+gvfs_file_info_populate_default (GFileInfo *info,
+ const char *name_string,
+ GFileType type)
+{
+ char *edit_name;
+
+ g_return_if_fail (G_IS_FILE_INFO (info));
+ g_return_if_fail (name_string != NULL);
+
+ edit_name = gvfs_file_info_populate_names_as_local (info, name_string);
+ gvfs_file_info_populate_content_types (info, edit_name, type);
+ g_free (edit_name);
+}
+
+/**
+ * gvfs_file_info_populate_names_as_local:
+ * @info: the file info to fill
+ * @name_string: a bytes string of possibly the full path to the given file
+ *
+ * Sets the name of the file info to @name_string and determines display and
+ * edit name for it.
+ *
+ * This generates the display name based on what encoding is used for local filenames.
+ * It might be a good thing to use if you have no idea of the remote system filename
+ * encoding, but if you know the actual encoding use, or if you allow per-mount
+ * configuration of filename encoding in your backend you should not use this.
+ *
+ * Returns: the utf-8 encoded edit name for the given file.
+ **/
+char *
+gvfs_file_info_populate_names_as_local (GFileInfo *info,
+ const char *name_string)
+{
+ //const char *slash;
+ char *edit_name;
+
+ g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
+ g_return_val_if_fail (name_string != NULL, NULL);
+
+#if 0
+ slash = strrchr (name_string, '/');
+ if (slash && slash[1])
+ name_string = slash + 1;
+#endif
+ edit_name = g_filename_display_basename (name_string);
+ g_file_info_set_edit_name (info, edit_name);
+
+ if (strstr (edit_name, "\357\277\275") != NULL)
+ {
+ char *display_name;
+
+ display_name = g_strconcat (edit_name, _(" (invalid encoding)"), NULL);
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+ else
+ g_file_info_set_display_name (info, edit_name);
+
+ return edit_name;
+}
+
+/**
+ * gvfs_file_info_populate_content_types:
+ * @info: the file info to fill
+ * @basename: utf-8 encoded base name of file
+ * @type: type of this file
+ *
+ * Takes the base name and guesses content type and icon with it. This function
+ * is intended for remote files. Do not use it for directories.
+ **/
+void
+gvfs_file_info_populate_content_types (GFileInfo *info,
+ const char *basename,
+ GFileType type)
+{
+ char *free_mimetype = NULL;
+ const char *mimetype;
+ GIcon *icon;
+
+ g_return_if_fail (G_IS_FILE_INFO (info));
+ g_return_if_fail (basename != NULL);
+
+ g_file_info_set_file_type (info, type);
+
+ switch (type)
+ {
+ case G_FILE_TYPE_DIRECTORY:
+ mimetype = "inode/directory";
+ break;
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ mimetype = "inode/symlink";
+ break;
+ case G_FILE_TYPE_SPECIAL:
+ mimetype = "inode/special";
+ break;
+ case G_FILE_TYPE_SHORTCUT:
+ mimetype = "inode/shortcut";
+ break;
+ case G_FILE_TYPE_MOUNTABLE:
+ mimetype = "inode/mountable";
+ break;
+ case G_FILE_TYPE_REGULAR:
+ free_mimetype = g_content_type_guess (basename, NULL, 0, NULL);
+ mimetype = free_mimetype;
+ break;
+ case G_FILE_TYPE_UNKNOWN:
+ default:
+ mimetype = "application/octet-stream";
+ break;
+ }
+
+ g_file_info_set_content_type (info, mimetype);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, mimetype);
+
+ if (type == G_FILE_TYPE_DIRECTORY)
+ icon = g_themed_icon_new ("folder");
+ else
+ {
+ icon = g_content_type_get_icon (mimetype);
+ }
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+
+ g_free (free_mimetype);
+}
+
diff --git a/trunk/daemon/gvfsdaemonutils.h b/trunk/daemon/gvfsdaemonutils.h
new file mode 100644
index 00000000..04b425fb
--- /dev/null
+++ b/trunk/daemon/gvfsdaemonutils.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_DAEMON_UTILS_H__
+#define __G_VFS_DAEMON_UTILS_H__
+
+#include <glib-object.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+void dbus_connection_add_fd_send_fd (DBusConnection *connection,
+ int extra_fd);
+gboolean dbus_connection_send_fd (DBusConnection *connection,
+ int fd,
+ int *fd_id,
+ GError **error);
+char * g_error_to_daemon_reply (GError *error,
+ guint32 seq_nr,
+ gsize *len_out);
+
+void gvfs_file_info_populate_default (GFileInfo *info,
+ const char *name_string,
+ GFileType type);
+char * gvfs_file_info_populate_names_as_local (GFileInfo *info,
+ const char *name_string);
+void gvfs_file_info_populate_content_types (GFileInfo *info,
+ const char *basename,
+ GFileType type);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DAEMON_UTILS_H__ */
diff --git a/trunk/daemon/gvfsjob.c b/trunk/daemon/gvfsjob.c
new file mode 100644
index 00000000..9aa168c2
--- /dev/null
+++ b/trunk/daemon/gvfsjob.c
@@ -0,0 +1,327 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include "gvfsjob.h"
+#include "gvfsjobsource.h"
+
+G_DEFINE_TYPE (GVfsJob, g_vfs_job, G_TYPE_OBJECT)
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+
+enum {
+ PROP_0
+};
+
+enum {
+ CANCELLED,
+ SEND_REPLY,
+ FINISHED,
+ NEW_SOURCE,
+ LAST_SIGNAL
+};
+
+struct _GVfsJobPrivate
+{
+ int dummy;
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void g_vfs_job_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void g_vfs_job_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void
+g_vfs_job_finalize (GObject *object)
+{
+ GVfsJob *job;
+
+ job = G_VFS_JOB (object);
+
+ if (job->error)
+ g_error_free (job->error);
+
+ if (job->backend_data_destroy)
+ job->backend_data_destroy (job->backend_data);
+
+ g_object_unref (job->cancellable);
+
+ if (G_OBJECT_CLASS (g_vfs_job_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_class_init (GVfsJobClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GVfsJobPrivate));
+
+ gobject_class->finalize = g_vfs_job_finalize;
+ gobject_class->set_property = g_vfs_job_set_property;
+ gobject_class->get_property = g_vfs_job_get_property;
+
+ signals[CANCELLED] =
+ g_signal_new ("cancelled",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsJobClass, cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[FINISHED] =
+ g_signal_new ("finished",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GVfsJobClass, finished),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[NEW_SOURCE] =
+ g_signal_new ("new-source",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsJobClass, new_source),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_VFS_TYPE_JOB_SOURCE);
+ signals[SEND_REPLY] =
+ g_signal_new ("send-reply",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsJobClass, send_reply),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+g_vfs_job_init (GVfsJob *job)
+{
+ job->priv = G_TYPE_INSTANCE_GET_PRIVATE (job, G_VFS_TYPE_JOB, GVfsJobPrivate);
+
+ job->cancellable = g_cancellable_new ();
+
+}
+
+void
+g_vfs_job_set_backend_data (GVfsJob *job,
+ gpointer backend_data,
+ GDestroyNotify destroy)
+{
+ if (job->backend_data_destroy)
+ {
+ job->backend_data_destroy (job->backend_data);
+ }
+
+ job->backend_data = backend_data;
+ job->backend_data_destroy = destroy;
+}
+
+static void
+g_vfs_job_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_job_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+void
+g_vfs_job_run (GVfsJob *job)
+{
+ GVfsJobClass *class;
+
+ class = G_VFS_JOB_GET_CLASS (job);
+
+ /* Ensure that the job lives durint the whole
+ * lifetime of the call, as it may disappear when
+ * we call g_vfs_job_succeed/fail()
+ */
+ g_object_ref (job);
+
+ class->run (job);
+
+ g_object_unref (job);
+}
+
+gboolean
+g_vfs_job_try (GVfsJob *job)
+{
+ GVfsJobClass *class;
+ gboolean res;
+
+ class = G_VFS_JOB_GET_CLASS (job);
+
+ /* Ensure that the job lives during the whole
+ * lifetime of the call, as it may disappear when
+ * we call g_vfs_job_succeed/fail()
+ */
+ g_object_ref (job);
+ res = class->try (job);
+ g_object_unref (job);
+
+ return res;
+}
+
+void
+g_vfs_job_cancel (GVfsJob *job)
+{
+ if (job->cancelled || job->sent_reply)
+ return;
+
+ job->cancelled = TRUE;
+ g_signal_emit (job, signals[CANCELLED], 0);
+ g_cancellable_cancel (job->cancellable);
+}
+
+static void
+g_vfs_job_send_reply (GVfsJob *job)
+{
+ job->sent_reply = TRUE;
+ g_signal_emit (job, signals[SEND_REPLY], 0);
+}
+
+void
+g_vfs_job_failed (GVfsJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...)
+{
+ va_list args;
+ char *message;
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ g_vfs_job_failed_literal (job, domain, code, message);
+ g_free (message);
+}
+
+void
+g_vfs_job_failed_literal (GVfsJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *message)
+{
+ if (job->failed)
+ return;
+
+ job->failed = TRUE;
+
+ job->error = g_error_new_literal (domain, code, message);
+
+ g_vfs_job_send_reply (job);
+}
+
+void
+g_vfs_job_failed_from_error (GVfsJob * job,
+ const GError *error)
+{
+ if (job->failed)
+ return;
+
+ job->failed = TRUE;
+ job->error = g_error_copy (error);
+ g_vfs_job_send_reply (job);
+}
+
+void
+g_vfs_job_failed_from_errno (GVfsJob *job,
+ gint errno_arg)
+{
+ GError *error = NULL;
+
+ g_set_error_literal (&error, G_IO_ERROR,
+ g_io_error_from_errno (errno_arg),
+ g_strerror (errno_arg));
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+}
+
+void
+g_vfs_job_succeeded (GVfsJob *job)
+{
+ job->failed = FALSE;
+ g_vfs_job_send_reply (job);
+}
+
+
+gboolean
+g_vfs_job_is_finished (GVfsJob *job)
+{
+ return job->finished;
+}
+
+gboolean
+g_vfs_job_is_cancelled (GVfsJob *job)
+{
+ return job->cancelled;
+}
+
+/* Might be called on an i/o thread */
+void
+g_vfs_job_emit_finished (GVfsJob *job)
+{
+ g_assert (!job->finished);
+
+ job->finished = TRUE;
+ g_signal_emit (job, signals[FINISHED], 0);
+}
diff --git a/trunk/daemon/gvfsjob.h b/trunk/daemon/gvfsjob.h
new file mode 100644
index 00000000..254f7ac7
--- /dev/null
+++ b/trunk/daemon/gvfsjob.h
@@ -0,0 +1,108 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_H__
+#define __G_VFS_JOB_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB (g_vfs_job_get_type ())
+#define G_VFS_JOB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB, GVfsJob))
+#define G_VFS_JOB_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB, GVfsJobClass))
+#define G_VFS_IS_JOB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB))
+#define G_VFS_IS_JOB_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB))
+#define G_VFS_JOB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB, GVfsJobClass))
+
+typedef struct _GVfsJob GVfsJob;
+typedef struct _GVfsJobPrivate GVfsJobPrivate;
+typedef struct _GVfsJobClass GVfsJobClass;
+
+/* Defined here to avoid circular includes */
+typedef struct _GVfsJobSource GVfsJobSource;
+
+struct _GVfsJob
+{
+ GObject parent_instance;
+
+ /* TODO: Move stuff to private */
+ gpointer backend_data;
+ GDestroyNotify backend_data_destroy;
+
+ guint failed : 1;
+ guint cancelled : 1;
+ guint sent_reply : 1;
+ guint finished : 1;
+ GError *error;
+ GCancellable *cancellable;
+
+ GVfsJobPrivate *priv;
+};
+
+struct _GVfsJobClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*cancelled) (GVfsJob *job);
+ void (*send_reply) (GVfsJob *job);
+ void (*new_source) (GVfsJob *job,
+ GVfsJobSource *job_source);
+ void (*finished) (GVfsJob *job);
+
+ /* vtable */
+
+ void (*run) (GVfsJob *job);
+ gboolean (*try) (GVfsJob *job);
+};
+
+GType g_vfs_job_get_type (void) G_GNUC_CONST;
+
+void g_vfs_job_set_backend_data (GVfsJob *job,
+ gpointer backend_data,
+ GDestroyNotify destroy);
+gboolean g_vfs_job_is_finished (GVfsJob *job);
+gboolean g_vfs_job_is_cancelled (GVfsJob *job);
+void g_vfs_job_cancel (GVfsJob *job);
+void g_vfs_job_run (GVfsJob *job);
+gboolean g_vfs_job_try (GVfsJob *job);
+void g_vfs_job_emit_finished (GVfsJob *job);
+void g_vfs_job_failed (GVfsJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (4, 5);
+void g_vfs_job_failed_literal (GVfsJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *message);
+void g_vfs_job_failed_from_error (GVfsJob *job,
+ const GError*error);
+void g_vfs_job_failed_from_errno (GVfsJob *job,
+ gint errno_arg);
+void g_vfs_job_succeeded (GVfsJob *job);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_H__ */
diff --git a/trunk/daemon/gvfsjobcloseread.c b/trunk/daemon/gvfsjobcloseread.c
new file mode 100644
index 00000000..217dfedc
--- /dev/null
+++ b/trunk/daemon/gvfsjobcloseread.c
@@ -0,0 +1,133 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobcloseread.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobCloseRead, g_vfs_job_close_read, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_close_read_finalize (GObject *object)
+{
+ GVfsJobCloseRead *job;
+
+ job = G_VFS_JOB_CLOSE_READ (object);
+ g_object_unref (job->channel);
+
+ if (G_OBJECT_CLASS (g_vfs_job_close_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_close_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_close_read_class_init (GVfsJobCloseReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_close_read_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_close_read_init (GVfsJobCloseRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_close_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ GVfsBackend *backend)
+{
+ GVfsJobCloseRead *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_CLOSE_READ,
+ NULL);
+
+ job->channel = g_object_ref (channel);
+ job->backend = backend;
+ job->handle = handle;
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobCloseRead *op_job = G_VFS_JOB_CLOSE_READ (job);
+
+ g_debug ("job_close_read send reply\n");
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ g_vfs_read_channel_send_closed (op_job->channel);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobCloseRead *op_job = G_VFS_JOB_CLOSE_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->close_read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->close_read (op_job->backend,
+ op_job,
+ op_job->handle);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobCloseRead *op_job = G_VFS_JOB_CLOSE_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_close_read == NULL)
+ return FALSE;
+
+ return class->try_close_read (op_job->backend,
+ op_job,
+ op_job->handle);
+}
diff --git a/trunk/daemon/gvfsjobcloseread.h b/trunk/daemon/gvfsjobcloseread.h
new file mode 100644
index 00000000..6ef33341
--- /dev/null
+++ b/trunk/daemon/gvfsjobcloseread.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_CLOSE_READ_H__
+#define __G_VFS_JOB_CLOSE_READ_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_CLOSE_READ (g_vfs_job_close_read_get_type ())
+#define G_VFS_JOB_CLOSE_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_CLOSE_READ, GVfsJobCloseRead))
+#define G_VFS_JOB_CLOSE_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_CLOSE_READ, GVfsJobCloseReadClass))
+#define G_VFS_IS_JOB_CLOSE_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_CLOSE_READ))
+#define G_VFS_IS_JOB_CLOSE_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_CLOSE_READ))
+#define G_VFS_JOB_CLOSE_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_CLOSE_READ, GVfsJobCloseReadClass))
+
+typedef struct _GVfsJobCloseReadClass GVfsJobCloseReadClass;
+
+struct _GVfsJobCloseRead
+{
+ GVfsJob parent_instance;
+
+ GVfsReadChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+};
+
+struct _GVfsJobCloseReadClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_close_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_close_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_CLOSE_READ_H__ */
diff --git a/trunk/daemon/gvfsjobclosewrite.c b/trunk/daemon/gvfsjobclosewrite.c
new file mode 100644
index 00000000..e621c51a
--- /dev/null
+++ b/trunk/daemon/gvfsjobclosewrite.c
@@ -0,0 +1,141 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfswritechannel.h"
+#include "gvfsjobclosewrite.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobCloseWrite, g_vfs_job_close_write, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_close_write_finalize (GObject *object)
+{
+ GVfsJobCloseWrite *job;
+
+ job = G_VFS_JOB_CLOSE_WRITE (object);
+ g_object_unref (job->channel);
+ g_free (job->etag);
+
+ if (G_OBJECT_CLASS (g_vfs_job_close_write_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_close_write_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_close_write_class_init (GVfsJobCloseWriteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_close_write_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_close_write_init (GVfsJobCloseWrite *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_close_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ GVfsBackend *backend)
+{
+ GVfsJobCloseWrite *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_CLOSE_WRITE,
+ NULL);
+
+ job->channel = g_object_ref (channel);
+ job->backend = backend;
+ job->handle = handle;
+
+ return G_VFS_JOB (job);
+}
+
+void
+g_vfs_job_close_write_set_etag (GVfsJobCloseWrite *job,
+ const char *etag)
+{
+ job->etag = g_strdup (etag);
+}
+
+/* Might be called on an i/o thwrite */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobCloseWrite *op_job = G_VFS_JOB_CLOSE_WRITE (job);
+
+ g_debug ("job_close_write send reply\n");
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ g_vfs_write_channel_send_closed (op_job->channel, op_job->etag ? op_job->etag : "");
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobCloseWrite *op_job = G_VFS_JOB_CLOSE_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->close_write == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->close_write (op_job->backend,
+ op_job,
+ op_job->handle);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobCloseWrite *op_job = G_VFS_JOB_CLOSE_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_close_write == NULL)
+ return FALSE;
+
+ return class->try_close_write (op_job->backend,
+ op_job,
+ op_job->handle);
+}
diff --git a/trunk/daemon/gvfsjobclosewrite.h b/trunk/daemon/gvfsjobclosewrite.h
new file mode 100644
index 00000000..6b4bf4ee
--- /dev/null
+++ b/trunk/daemon/gvfsjobclosewrite.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_CLOSE_WRITE_H__
+#define __G_VFS_JOB_CLOSE_WRITE_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfswritechannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_CLOSE_WRITE (g_vfs_job_close_write_get_type ())
+#define G_VFS_JOB_CLOSE_WRITE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_CLOSE_WRITE, GVfsJobCloseWrite))
+#define G_VFS_JOB_CLOSE_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_CLOSE_WRITE, GVfsJobCloseWriteClass))
+#define G_VFS_IS_JOB_CLOSE_WRITE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_CLOSE_WRITE))
+#define G_VFS_IS_JOB_CLOSE_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_CLOSE_WRITE))
+#define G_VFS_JOB_CLOSE_WRITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_CLOSE_WRITE, GVfsJobCloseWriteClass))
+
+typedef struct _GVfsJobCloseWriteClass GVfsJobCloseWriteClass;
+
+struct _GVfsJobCloseWrite
+{
+ GVfsJob parent_instance;
+
+ char *etag;
+ GVfsWriteChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+};
+
+struct _GVfsJobCloseWriteClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_close_write_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_close_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ GVfsBackend *backend);
+
+void g_vfs_job_close_write_set_etag (GVfsJobCloseWrite *job,
+ const char *etag);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_CLOSE_WRITE_H__ */
diff --git a/trunk/daemon/gvfsjobcopy.c b/trunk/daemon/gvfsjobcopy.c
new file mode 100644
index 00000000..4463aa25
--- /dev/null
+++ b/trunk/daemon/gvfsjobcopy.c
@@ -0,0 +1,211 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobcopy.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobCopy, g_vfs_job_copy, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_copy_finalize (GObject *object)
+{
+ GVfsJobCopy *job;
+
+ job = G_VFS_JOB_COPY (object);
+
+ g_free (job->source);
+ g_free (job->destination);
+ g_free (job->callback_obj_path);
+
+ if (G_OBJECT_CLASS (g_vfs_job_copy_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_copy_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_copy_class_init (GVfsJobCopyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_copy_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_copy_init (GVfsJobCopy *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_copy_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobCopy *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path1_len, path2_len;
+ const char *path1_data, *path2_data, *callback_obj_path;
+ dbus_uint32_t flags;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path1_data, &path1_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path2_data, &path2_len,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_COPY,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->source = g_strndup (path1_data, path1_len);
+ job->destination = g_strndup (path2_data, path2_len);
+ job->backend = backend;
+ job->flags = flags;
+ if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
+ job->callback_obj_path = g_strdup (callback_obj_path);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (user_data);
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ GVfsJobCopy *op_job = G_VFS_JOB_COPY (job);
+ dbus_uint64_t current_dbus, total_dbus;
+ DBusMessage *message;
+
+ g_debug ("progress_callback %d/%d\n", (int)current_num_bytes, (int)total_num_bytes);
+
+ if (op_job->callback_obj_path == NULL)
+ return;
+
+ message =
+ dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
+ op_job->callback_obj_path,
+ G_VFS_DBUS_PROGRESS_INTERFACE,
+ G_VFS_DBUS_PROGRESS_OP_PROGRESS);
+ dbus_message_set_no_reply (message, TRUE);
+
+ current_dbus = current_num_bytes;
+ total_dbus = total_num_bytes;
+ dbus_message_append_args (message,
+ DBUS_TYPE_UINT64, &current_dbus,
+ DBUS_TYPE_UINT64, &total_dbus,
+ 0);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, message, NULL);
+ dbus_message_unref (message);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobCopy *op_job = G_VFS_JOB_COPY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->copy == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->copy (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->destination,
+ op_job->flags,
+ progress_callback,
+ job);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobCopy *op_job = G_VFS_JOB_COPY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_copy == NULL)
+ return FALSE;
+
+ return class->try_copy (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->destination,
+ op_job->flags,
+ progress_callback,
+ job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobcopy.h b/trunk/daemon/gvfsjobcopy.h
new file mode 100644
index 00000000..20a8b7be
--- /dev/null
+++ b/trunk/daemon/gvfsjobcopy.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_COPY_H__
+#define __G_VFS_JOB_COPY_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_COPY (g_vfs_job_copy_get_type ())
+#define G_VFS_JOB_COPY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_COPY, GVfsJobCopy))
+#define G_VFS_JOB_COPY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_COPY, GVfsJobCopyClass))
+#define G_VFS_IS_JOB_COPY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_COPY))
+#define G_VFS_IS_JOB_COPY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_COPY))
+#define G_VFS_JOB_COPY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_COPY, GVfsJobCopyClass))
+
+typedef struct _GVfsJobCopyClass GVfsJobCopyClass;
+
+struct _GVfsJobCopy
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *source;
+ char *destination;
+ GFileCopyFlags flags;
+ char *callback_obj_path;
+
+};
+
+struct _GVfsJobCopyClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_copy_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_copy_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_COPY_H__ */
diff --git a/trunk/daemon/gvfsjobcreatemonitor.c b/trunk/daemon/gvfsjobcreatemonitor.c
new file mode 100644
index 00000000..4878373f
--- /dev/null
+++ b/trunk/daemon/gvfsjobcreatemonitor.c
@@ -0,0 +1,246 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobcreatemonitor.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobCreateMonitor, g_vfs_job_create_monitor, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_create_monitor_finalize (GObject *object)
+{
+ GVfsJobCreateMonitor *job;
+
+ job = G_VFS_JOB_CREATE_MONITOR (object);
+
+ g_free (job->filename);
+ if (job->monitor)
+ g_object_unref (job->monitor);
+
+ if (G_OBJECT_CLASS (g_vfs_job_create_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_create_monitor_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_create_monitor_class_init (GVfsJobCreateMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_create_monitor_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_create_monitor_init (GVfsJobCreateMonitor *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_create_monitor_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean is_directory)
+{
+ GVfsJobCreateMonitor *job;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusError derror;
+ char *path;
+ guint32 flags;
+
+ dbus_error_init (&derror);
+ dbus_message_iter_init (message, &iter);
+
+ path = NULL;
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ G_DBUS_TYPE_CSTRING, &path,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ g_free (path);
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_CREATE_MONITOR,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->is_directory = is_directory;
+ job->filename = path;
+ job->backend = backend;
+ job->flags = flags;
+
+ return G_VFS_JOB (job);
+}
+
+void
+g_vfs_job_create_monitor_set_monitor (GVfsJobCreateMonitor *job,
+ GVfsMonitor *monitor)
+{
+ job->monitor = g_object_ref (monitor);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobCreateMonitor *op_job = G_VFS_JOB_CREATE_MONITOR (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->is_directory)
+ {
+ if (class->create_dir_monitor == NULL)
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ else
+ class->create_dir_monitor (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else
+ {
+ if (class->create_file_monitor == NULL)
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ else
+ class->create_file_monitor (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobCreateMonitor *op_job = G_VFS_JOB_CREATE_MONITOR (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->is_directory)
+ {
+ if (class->try_create_dir_monitor == NULL)
+ {
+ if (class->create_dir_monitor == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ return class->try_create_dir_monitor (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else
+ {
+ if (class->try_create_file_monitor == NULL)
+ {
+ if (class->create_file_monitor == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ return class->try_create_file_monitor (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+}
+
+static gboolean
+unref_monitor_timeout (gpointer data)
+{
+ GVfsMonitor *monitor = data;
+
+ /* Unref the refcount for the VfsMonitor that we returned.
+ If we didn't get an initial subscriber this is where we free the
+ monitor */
+ g_object_unref (monitor);
+
+ return FALSE;
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobCreateMonitor *op_job = G_VFS_JOB_CREATE_MONITOR (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ const char *obj_path;
+
+ reply = dbus_message_new_method_return (message);
+
+ /* Keep the monitor alive for at least 5 seconds
+ to allow for a subscribe call to come in and bump
+ the refcount */
+ g_object_ref (op_job->monitor);
+ g_timeout_add_seconds (5,
+ unref_monitor_timeout,
+ op_job->monitor);
+
+ obj_path = g_vfs_monitor_get_object_path (op_job->monitor);
+ dbus_message_iter_init_append (reply, &iter);
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobcreatemonitor.h b/trunk/daemon/gvfsjobcreatemonitor.h
new file mode 100644
index 00000000..f3277d34
--- /dev/null
+++ b/trunk/daemon/gvfsjobcreatemonitor.h
@@ -0,0 +1,71 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_CREATE_MONITOR_H__
+#define __G_VFS_JOB_CREATE_MONITOR_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+#include <gvfsmonitor.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_CREATE_MONITOR (g_vfs_job_create_monitor_get_type ())
+#define G_VFS_JOB_CREATE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_CREATE_MONITOR, GVfsJobCreateMonitor))
+#define G_VFS_JOB_CREATE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_CREATE_MONITOR, GVfsJobCreateMonitorClass))
+#define G_VFS_IS_JOB_CREATE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_CREATE_MONITOR))
+#define G_VFS_IS_JOB_CREATE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_CREATE_MONITOR))
+#define G_VFS_JOB_CREATE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_CREATE_MONITOR, GVfsJobCreateMonitorClass))
+
+typedef struct _GVfsJobCreateMonitorClass GVfsJobCreateMonitorClass;
+
+struct _GVfsJobCreateMonitor
+{
+ GVfsJobDBus parent_instance;
+
+ gboolean is_directory;
+ GVfsBackend *backend;
+ char *filename;
+ GFileMonitorFlags flags;
+
+ GVfsMonitor *monitor;
+};
+
+struct _GVfsJobCreateMonitorClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_create_monitor_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_create_monitor_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean is_directory);
+void g_vfs_job_create_monitor_set_monitor (GVfsJobCreateMonitor *job,
+ GVfsMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_CREATE_MONITOR_H__ */
diff --git a/trunk/daemon/gvfsjobdbus.c b/trunk/daemon/gvfsjobdbus.c
new file mode 100644
index 00000000..3a1bf4ea
--- /dev/null
+++ b/trunk/daemon/gvfsjobdbus.c
@@ -0,0 +1,196 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobdbus.h"
+#include "gdbusutils.h"
+
+G_DEFINE_TYPE (GVfsJobDBus, g_vfs_job_dbus, G_VFS_TYPE_JOB)
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+
+enum {
+ PROP_0,
+ PROP_MESSAGE,
+ PROP_CONNECTION
+};
+
+static void send_reply (GVfsJob *job);
+static void g_vfs_job_dbus_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void g_vfs_job_dbus_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void
+g_vfs_job_dbus_finalize (GObject *object)
+{
+ GVfsJobDBus *job;
+
+ job = G_VFS_JOB_DBUS (object);
+
+ if (job->message)
+ dbus_message_unref (job->message);
+
+ if (job->connection)
+ dbus_connection_unref (job->connection);
+
+ if (G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_dbus_class_init (GVfsJobDBusClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_dbus_finalize;
+ gobject_class->set_property = g_vfs_job_dbus_set_property;
+ gobject_class->get_property = g_vfs_job_dbus_get_property;
+
+ job_class->send_reply = send_reply;
+
+ g_object_class_install_property (gobject_class,
+ PROP_CONNECTION,
+ g_param_spec_pointer ("connection",
+ P_("VFS Backend"),
+ P_("The implementation for this job operartion."),
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (gobject_class,
+ PROP_MESSAGE,
+ g_param_spec_pointer ("message",
+ P_("VFS Backend"),
+ P_("The implementation for this job operartion."),
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+}
+
+static void
+g_vfs_job_dbus_init (GVfsJobDBus *job)
+{
+}
+
+static void
+g_vfs_job_dbus_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsJobDBus *job = G_VFS_JOB_DBUS (object);
+
+ switch (prop_id)
+ {
+ case PROP_MESSAGE:
+ job->message = dbus_message_ref (g_value_get_pointer (value));
+ break;
+ case PROP_CONNECTION:
+ job->connection = dbus_connection_ref (g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_vfs_job_dbus_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVfsJobDBus *job = G_VFS_JOB_DBUS (object);
+
+ switch (prop_id)
+ {
+ case PROP_MESSAGE:
+ g_value_set_pointer (value, job->message);
+ break;
+ case PROP_CONNECTION:
+ g_value_set_pointer (value, job->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ DBusMessage *reply;
+ GVfsJobDBusClass *class;
+
+ g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:"");
+
+ class = G_VFS_JOB_DBUS_GET_CLASS (job);
+
+ if (job->failed)
+ reply = _dbus_message_new_from_gerror (dbus_job->message, job->error);
+ else
+ reply = class->create_reply (job, dbus_job->connection, dbus_job->message);
+
+ g_assert (reply != NULL);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ g_vfs_job_emit_finished (job);
+}
+
+DBusConnection *
+g_vfs_job_dbus_get_connection (GVfsJobDBus *job_dbus)
+{
+ return job_dbus->connection;
+}
+
+DBusMessage *
+g_vfs_job_dbus_get_message (GVfsJobDBus *job_dbus)
+{
+ return job_dbus->message;
+}
+
+gboolean
+g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus,
+ DBusConnection *connection,
+ dbus_uint32_t serial)
+{
+ return job_dbus->connection == connection &&
+ dbus_message_get_serial (job_dbus->message) == serial;
+}
diff --git a/trunk/daemon/gvfsjobdbus.h b/trunk/daemon/gvfsjobdbus.h
new file mode 100644
index 00000000..05948188
--- /dev/null
+++ b/trunk/daemon/gvfsjobdbus.h
@@ -0,0 +1,70 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_DBUS_H__
+#define __G_VFS_JOB_DBUS_H__
+
+#include <dbus/dbus.h>
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_DBUS (g_vfs_job_dbus_get_type ())
+#define G_VFS_JOB_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_DBUS, GVfsJobDBus))
+#define G_VFS_JOB_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_DBUS, GVfsJobDBusClass))
+#define G_VFS_IS_JOB_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_DBUS))
+#define G_VFS_IS_JOB_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_DBUS))
+#define G_VFS_JOB_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_DBUS, GVfsJobDBusClass))
+
+typedef struct _GVfsJobDBus GVfsJobDBus;
+typedef struct _GVfsJobDBusClass GVfsJobDBusClass;
+
+struct _GVfsJobDBus
+{
+ GVfsJob parent_instance;
+
+ DBusConnection *connection;
+ DBusMessage *message;
+};
+
+struct _GVfsJobDBusClass
+{
+ GVfsJobClass parent_class;
+
+ /* Might be called on an i/o thread */
+ DBusMessage * (*create_reply) (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+};
+
+GType g_vfs_job_dbus_get_type (void) G_GNUC_CONST;
+
+gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus,
+ DBusConnection *connection,
+ dbus_uint32_t serial);
+DBusConnection *g_vfs_job_dbus_get_connection (GVfsJobDBus *job_dbus);
+DBusMessage *g_vfs_job_dbus_get_message (GVfsJobDBus *job_dbus);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_DBUS_H__ */
diff --git a/trunk/daemon/gvfsjobdelete.c b/trunk/daemon/gvfsjobdelete.c
new file mode 100644
index 00000000..b65ec299
--- /dev/null
+++ b/trunk/daemon/gvfsjobdelete.c
@@ -0,0 +1,156 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobdelete.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobDelete, g_vfs_job_delete, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_delete_finalize (GObject *object)
+{
+ GVfsJobDelete *job;
+
+ job = G_VFS_JOB_DELETE (object);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_delete_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_delete_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_delete_class_init (GVfsJobDeleteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_delete_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_delete_init (GVfsJobDelete *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_delete_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobDelete *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_DELETE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobDelete *op_job = G_VFS_JOB_DELETE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->delete == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->delete (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobDelete *op_job = G_VFS_JOB_DELETE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_delete == NULL)
+ return FALSE;
+
+ return class->try_delete (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobdelete.h b/trunk/daemon/gvfsjobdelete.h
new file mode 100644
index 00000000..10db6521
--- /dev/null
+++ b/trunk/daemon/gvfsjobdelete.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_DELETE_H__
+#define __G_VFS_JOB_DELETE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_DELETE (g_vfs_job_delete_get_type ())
+#define G_VFS_JOB_DELETE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_DELETE, GVfsJobDelete))
+#define G_VFS_JOB_DELETE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_DELETE, GVfsJobDeleteClass))
+#define G_VFS_IS_JOB_DELETE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_DELETE))
+#define G_VFS_IS_JOB_DELETE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_DELETE))
+#define G_VFS_JOB_DELETE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_DELETE, GVfsJobDeleteClass))
+
+typedef struct _GVfsJobDeleteClass GVfsJobDeleteClass;
+
+struct _GVfsJobDelete
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+};
+
+struct _GVfsJobDeleteClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_delete_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_delete_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_DELETE_H__ */
diff --git a/trunk/daemon/gvfsjobenumerate.c b/trunk/daemon/gvfsjobenumerate.c
new file mode 100644
index 00000000..01678e35
--- /dev/null
+++ b/trunk/daemon/gvfsjobenumerate.c
@@ -0,0 +1,320 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobenumerate.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobEnumerate, g_vfs_job_enumerate, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_enumerate_finalize (GObject *object)
+{
+ GVfsJobEnumerate *job;
+
+ job = G_VFS_JOB_ENUMERATE (object);
+
+ g_free (job->filename);
+ g_free (job->attributes);
+ g_file_attribute_matcher_unref (job->attribute_matcher);
+ g_free (job->object_path);
+ g_free (job->uri);
+
+ if (G_OBJECT_CLASS (g_vfs_job_enumerate_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_enumerate_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_enumerate_class_init (GVfsJobEnumerateClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_enumerate_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_enumerate_init (GVfsJobEnumerate *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_enumerate_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobEnumerate *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *obj_path;
+ const char *path_data;
+ char *attributes, *uri;
+ dbus_uint32_t flags;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init (message, &iter);
+ dbus_error_init (&derror);
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ DBUS_TYPE_STRING, &obj_path,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ /* Optional uri arg for thumbnail info */
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_STRING, &uri,
+ 0))
+ uri = NULL;
+
+ job = g_object_new (G_VFS_TYPE_JOB_ENUMERATE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->object_path = g_strdup (obj_path);
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+ job->attributes = g_strdup (attributes);
+ job->attribute_matcher = g_file_attribute_matcher_new (attributes);
+ job->flags = flags;
+ job->uri = g_strdup (uri);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+send_infos (GVfsJobEnumerate *job)
+{
+ if (!dbus_message_iter_close_container (&job->building_iter, &job->building_array_iter))
+ _g_dbus_oom ();
+
+ dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)),
+ job->building_infos, NULL);
+ dbus_message_unref (job->building_infos);
+ job->building_infos = NULL;
+ job->n_building_infos = 0;
+}
+
+void
+g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job,
+ GFileInfo *info)
+{
+ DBusMessage *message, *orig_message;
+ char *uri, *escaped_name;
+
+ if (job->building_infos == NULL)
+ {
+ orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job));
+
+ message = dbus_message_new_method_call (dbus_message_get_sender (orig_message),
+ job->object_path,
+ G_VFS_DBUS_ENUMERATOR_INTERFACE,
+ G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO);
+ dbus_message_set_no_reply (message, TRUE);
+
+ dbus_message_iter_init_append (message, &job->building_iter);
+
+ if (!dbus_message_iter_open_container (&job->building_iter,
+ DBUS_TYPE_ARRAY,
+ G_FILE_INFO_TYPE_AS_STRING,
+ &job->building_array_iter))
+ _g_dbus_oom ();
+
+ job->building_infos = message;
+ job->n_building_infos = 0;
+ }
+
+
+
+ uri = NULL;
+ if (job->uri != NULL &&
+ g_file_info_get_name (info) != NULL)
+ {
+ escaped_name = g_uri_escape_string (g_file_info_get_name (info),
+ G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,
+ FALSE);
+ uri = g_build_path ("/", job->uri, escaped_name, NULL);
+ g_free (escaped_name);
+ }
+
+ g_vfs_backend_add_auto_info (job->backend,
+ job->attribute_matcher,
+ info,
+ uri);
+ g_free (uri);
+
+ g_file_info_set_attribute_mask (info, job->attribute_matcher);
+
+ _g_dbus_append_file_info (&job->building_array_iter, info);
+ job->n_building_infos++;
+
+ if (job->n_building_infos == 50)
+ send_infos (job);
+}
+
+void
+g_vfs_job_enumerate_add_infos (GVfsJobEnumerate *job,
+ const GList *infos)
+{
+ const GList *l;
+ GFileInfo *info;
+
+ for (l = infos; l != NULL; l = l->next)
+ {
+ info = l->data;
+ g_vfs_job_enumerate_add_info (job, info);
+ }
+}
+
+void
+g_vfs_job_enumerate_done (GVfsJobEnumerate *job)
+{
+ DBusMessage *message, *orig_message;
+
+ g_assert (!G_VFS_JOB (job)->failed);
+
+ if (job->building_infos != NULL)
+ send_infos (job);
+
+ orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job));
+
+ message = dbus_message_new_method_call (dbus_message_get_sender (orig_message),
+ job->object_path,
+ G_VFS_DBUS_ENUMERATOR_INTERFACE,
+ G_VFS_DBUS_ENUMERATOR_OP_DONE);
+ dbus_message_set_no_reply (message, TRUE);
+
+ dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)),
+ message, NULL);
+ dbus_message_unref (message);
+
+ g_vfs_job_emit_finished (G_VFS_JOB (job));
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobEnumerate *op_job = G_VFS_JOB_ENUMERATE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->enumerate == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->enumerate (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute_matcher,
+ op_job->flags);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobEnumerate *op_job = G_VFS_JOB_ENUMERATE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_enumerate == NULL)
+ return FALSE;
+
+ return class->try_enumerate (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute_matcher,
+ op_job->flags);
+}
+
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ DBusMessage *reply;
+ GVfsJobDBusClass *class;
+
+ g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:"");
+
+ class = G_VFS_JOB_DBUS_GET_CLASS (job);
+
+ if (job->failed)
+ reply = _dbus_message_new_from_gerror (dbus_job->message, job->error);
+ else
+ reply = class->create_reply (job, dbus_job->connection, dbus_job->message);
+
+ g_assert (reply != NULL);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ if (job->failed)
+ g_vfs_job_emit_finished (job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobenumerate.h b/trunk/daemon/gvfsjobenumerate.h
new file mode 100644
index 00000000..731842e6
--- /dev/null
+++ b/trunk/daemon/gvfsjobenumerate.h
@@ -0,0 +1,78 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_ENUMERATE_H__
+#define __G_VFS_JOB_ENUMERATE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_ENUMERATE (g_vfs_job_enumerate_get_type ())
+#define G_VFS_JOB_ENUMERATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_ENUMERATE, GVfsJobEnumerate))
+#define G_VFS_JOB_ENUMERATE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_ENUMERATE, GVfsJobEnumerateClass))
+#define G_VFS_IS_JOB_ENUMERATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_ENUMERATE))
+#define G_VFS_IS_JOB_ENUMERATE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_ENUMERATE))
+#define G_VFS_JOB_ENUMERATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_ENUMERATE, GVfsJobEnumerateClass))
+
+typedef struct _GVfsJobEnumerateClass GVfsJobEnumerateClass;
+
+struct _GVfsJobEnumerate
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ char *object_path;
+ char *attributes;
+ GFileAttributeMatcher *attribute_matcher;
+ GFileQueryInfoFlags flags;
+ char *uri;
+
+ DBusMessage *building_infos;
+ DBusMessageIter building_iter;
+ DBusMessageIter building_array_iter;
+ int n_building_infos;
+};
+
+struct _GVfsJobEnumerateClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_enumerate_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_enumerate_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+void g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job,
+ GFileInfo *info);
+void g_vfs_job_enumerate_add_infos (GVfsJobEnumerate *job,
+ const GList *info);
+void g_vfs_job_enumerate_done (GVfsJobEnumerate *job);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_ENUMERATE_H__ */
diff --git a/trunk/daemon/gvfsjobmakedirectory.c b/trunk/daemon/gvfsjobmakedirectory.c
new file mode 100644
index 00000000..2e16b12d
--- /dev/null
+++ b/trunk/daemon/gvfsjobmakedirectory.c
@@ -0,0 +1,156 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmakedirectory.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobMakeDirectory, g_vfs_job_make_directory, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_make_directory_finalize (GObject *object)
+{
+ GVfsJobMakeDirectory *job;
+
+ job = G_VFS_JOB_MAKE_DIRECTORY (object);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_make_directory_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_make_directory_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_make_directory_class_init (GVfsJobMakeDirectoryClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_make_directory_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_make_directory_init (GVfsJobMakeDirectory *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_make_directory_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobMakeDirectory *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_MAKE_DIRECTORY,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMakeDirectory *op_job = G_VFS_JOB_MAKE_DIRECTORY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->make_directory == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->make_directory (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMakeDirectory *op_job = G_VFS_JOB_MAKE_DIRECTORY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_make_directory == NULL)
+ return FALSE;
+
+ return class->try_make_directory (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobmakedirectory.h b/trunk/daemon/gvfsjobmakedirectory.h
new file mode 100644
index 00000000..00cbaf0f
--- /dev/null
+++ b/trunk/daemon/gvfsjobmakedirectory.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_MAKE_DIRECTORY_H__
+#define __G_VFS_JOB_MAKE_DIRECTORY_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MAKE_DIRECTORY (g_vfs_job_make_directory_get_type ())
+#define G_VFS_JOB_MAKE_DIRECTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectory))
+#define G_VFS_JOB_MAKE_DIRECTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectoryClass))
+#define G_VFS_IS_JOB_MAKE_DIRECTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY))
+#define G_VFS_IS_JOB_MAKE_DIRECTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MAKE_DIRECTORY))
+#define G_VFS_JOB_MAKE_DIRECTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectoryClass))
+
+typedef struct _GVfsJobMakeDirectoryClass GVfsJobMakeDirectoryClass;
+
+struct _GVfsJobMakeDirectory
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+};
+
+struct _GVfsJobMakeDirectoryClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_make_directory_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_make_directory_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MAKE_DIRECTORY_H__ */
diff --git a/trunk/daemon/gvfsjobmakesymlink.c b/trunk/daemon/gvfsjobmakesymlink.c
new file mode 100644
index 00000000..898010fc
--- /dev/null
+++ b/trunk/daemon/gvfsjobmakesymlink.c
@@ -0,0 +1,162 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmakesymlink.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobMakeSymlink, g_vfs_job_make_symlink, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_make_symlink_finalize (GObject *object)
+{
+ GVfsJobMakeSymlink *job;
+
+ job = G_VFS_JOB_MAKE_SYMLINK (object);
+
+ g_free (job->filename);
+ g_free (job->symlink_value);
+
+ if (G_OBJECT_CLASS (g_vfs_job_make_symlink_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_make_symlink_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_make_symlink_class_init (GVfsJobMakeSymlinkClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_make_symlink_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_make_symlink_init (GVfsJobMakeSymlink *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_make_symlink_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobMakeSymlink *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len, symlink_len;
+ const char *path_data, *symlink_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &symlink_data, &symlink_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_MAKE_SYMLINK,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->symlink_value = g_strndup (symlink_data, symlink_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMakeSymlink *op_job = G_VFS_JOB_MAKE_SYMLINK (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->make_symlink == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Symlinks not supported by backend"));
+ return;
+ }
+
+ class->make_symlink (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->symlink_value);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMakeSymlink *op_job = G_VFS_JOB_MAKE_SYMLINK (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_make_symlink == NULL)
+ return FALSE;
+
+ return class->try_make_symlink (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->symlink_value);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobmakesymlink.h b/trunk/daemon/gvfsjobmakesymlink.h
new file mode 100644
index 00000000..a662f2b4
--- /dev/null
+++ b/trunk/daemon/gvfsjobmakesymlink.h
@@ -0,0 +1,64 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_MAKE_SYMLINK_H__
+#define __G_VFS_JOB_MAKE_SYMLINK_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MAKE_SYMLINK (g_vfs_job_make_symlink_get_type ())
+#define G_VFS_JOB_MAKE_SYMLINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MAKE_SYMLINK, GVfsJobMakeSymlink))
+#define G_VFS_JOB_MAKE_SYMLINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MAKE_SYMLINK, GVfsJobMakeSymlinkClass))
+#define G_VFS_IS_JOB_MAKE_SYMLINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MAKE_SYMLINK))
+#define G_VFS_IS_JOB_MAKE_SYMLINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MAKE_SYMLINK))
+#define G_VFS_JOB_MAKE_SYMLINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MAKE_SYMLINK, GVfsJobMakeSymlinkClass))
+
+typedef struct _GVfsJobMakeSymlinkClass GVfsJobMakeSymlinkClass;
+
+struct _GVfsJobMakeSymlink
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ char *symlink_value;
+};
+
+struct _GVfsJobMakeSymlinkClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_make_symlink_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_make_symlink_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MAKE_SYMLINK_H__ */
diff --git a/trunk/daemon/gvfsjobmount.c b/trunk/daemon/gvfsjobmount.c
new file mode 100644
index 00000000..d5196a98
--- /dev/null
+++ b/trunk/daemon/gvfsjobmount.c
@@ -0,0 +1,216 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmount.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobMount, g_vfs_job_mount, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_mount_finalize (GObject *object)
+{
+ GVfsJobMount *job;
+
+ job = G_VFS_JOB_MOUNT (object);
+
+ g_mount_spec_unref (job->mount_spec);
+ g_object_unref (job->mount_source);
+ g_object_unref (job->backend);
+
+ if (G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_mount_class_init (GVfsJobMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_mount_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_mount_init (GVfsJobMount *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_mount_new (GMountSpec *spec,
+ GMountSource *source,
+ gboolean is_automount,
+ DBusMessage *request,
+ GVfsBackend *backend)
+{
+ GVfsJobMount *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_MOUNT,
+ NULL);
+
+ job->mount_spec = g_mount_spec_ref (spec);
+ job->mount_source = g_object_ref (source);
+ job->is_automount = is_automount;
+ /* Ref the backend so we're sure its alive
+ during the whole job request. */
+ job->backend = g_object_ref (backend);
+ if (request)
+ job->request = dbus_message_ref (request);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMount *op_job = G_VFS_JOB_MOUNT (job);
+ GVfsBackend *backend = op_job->backend;
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (backend);
+
+ if (class->mount == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->mount (backend,
+ op_job,
+ op_job->mount_spec,
+ op_job->mount_source,
+ op_job->is_automount);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMount *op_job = G_VFS_JOB_MOUNT (job);
+ GVfsBackend *backend = op_job->backend;
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (backend);
+ gboolean result;
+
+ if (class->try_mount == NULL)
+ return FALSE;
+
+ result = class->try_mount (backend,
+ op_job,
+ op_job->mount_spec,
+ op_job->mount_source,
+ op_job->is_automount);
+ return result;
+}
+
+static void
+mount_failed (GVfsJobMount *op_job, GError *error)
+{
+ DBusConnection *conn;
+ DBusMessage *reply;
+ GVfsBackend *backend;
+
+ if (op_job->request)
+ {
+ reply = _dbus_message_new_from_gerror (op_job->request, error);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+ dbus_connection_unref (conn);
+ }
+ }
+ else
+ g_debug ("Mount failed: %s\n", error->message);
+
+ backend = g_object_ref (op_job->backend);
+ g_vfs_job_emit_finished (G_VFS_JOB (op_job));
+
+ /* Remove failed backend from daemon */
+ g_vfs_job_source_closed (G_VFS_JOB_SOURCE (backend));
+ g_object_unref (backend);
+}
+
+static void
+register_mount_callback (DBusMessage *mount_reply,
+ GError *error,
+ gpointer user_data)
+{
+ GVfsJobMount *op_job = G_VFS_JOB_MOUNT (user_data);
+ DBusConnection *conn;
+ DBusMessage *reply;
+
+ g_debug ("register_mount_callback, mount_reply: %p, error: %p\n", mount_reply, error);
+
+ if (mount_reply == NULL)
+ mount_failed (op_job, error);
+ else
+ {
+ if (op_job->request)
+ {
+ reply = dbus_message_new_method_return (op_job->request);
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+ dbus_connection_unref (conn);
+ }
+ }
+
+ g_vfs_job_emit_finished (G_VFS_JOB (op_job));
+ }
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobMount *op_job = G_VFS_JOB_MOUNT (job);
+
+ g_debug ("send_reply, failed: %d\n", job->failed);
+
+ if (job->failed)
+ mount_failed (op_job, job->error);
+ else
+ g_vfs_backend_register_mount (op_job->backend,
+ register_mount_callback,
+ job);
+}
diff --git a/trunk/daemon/gvfsjobmount.h b/trunk/daemon/gvfsjobmount.h
new file mode 100644
index 00000000..8e8f312e
--- /dev/null
+++ b/trunk/daemon/gvfsjobmount.h
@@ -0,0 +1,68 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_MOUNT_H__
+#define __G_VFS_JOB_MOUNT_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MOUNT (g_vfs_job_mount_get_type ())
+#define G_VFS_JOB_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MOUNT, GVfsJobMount))
+#define G_VFS_JOB_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MOUNT, GVfsJobMountClass))
+#define G_VFS_IS_JOB_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MOUNT))
+#define G_VFS_IS_JOB_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MOUNT))
+#define G_VFS_JOB_MOUNT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MOUNT, GVfsJobMountClass))
+
+typedef struct _GVfsJobMountClass GVfsJobMountClass;
+
+struct _GVfsJobMount
+{
+ GVfsJob parent_instance;
+
+ GVfsBackend *backend;
+ gboolean is_automount;
+ GMountSpec *mount_spec;
+ GMountSource *mount_source;
+ DBusMessage *request;
+};
+
+struct _GVfsJobMountClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_mount_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_mount_new (GMountSpec *spec,
+ GMountSource *source,
+ gboolean is_automount,
+ DBusMessage *request,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MOUNT_H__ */
diff --git a/trunk/daemon/gvfsjobmountmountable.c b/trunk/daemon/gvfsjobmountmountable.c
new file mode 100644
index 00000000..4397bc1f
--- /dev/null
+++ b/trunk/daemon/gvfsjobmountmountable.c
@@ -0,0 +1,216 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmountmountable.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobMountMountable, g_vfs_job_mount_mountable, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_mount_mountable_finalize (GObject *object)
+{
+ GVfsJobMountMountable *job;
+
+ job = G_VFS_JOB_MOUNT_MOUNTABLE (object);
+
+ if (job->mount_source)
+ g_object_unref (job->mount_source);
+
+ if (job->mount_spec)
+ g_mount_spec_unref (job->mount_spec);
+
+ g_free (job->filename);
+ g_free (job->target_filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_mount_mountable_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_mount_mountable_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_mount_mountable_class_init (GVfsJobMountMountableClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_mount_mountable_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_mount_mountable_init (GVfsJobMountMountable *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_mount_mountable_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobMountMountable *job;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusError derror;
+ char *path;
+ const char *dbus_id, *obj_path;
+
+ dbus_error_init (&derror);
+ dbus_message_iter_init (message, &iter);
+
+ path = NULL;
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ G_DBUS_TYPE_CSTRING, &path,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0))
+ {
+ g_free (path);
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_MOUNT_MOUNTABLE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = path;
+ job->backend = backend;
+ job->mount_source = g_mount_source_new (dbus_id, obj_path);
+
+ return G_VFS_JOB (job);
+}
+
+void
+g_vfs_job_mount_mountable_set_target (GVfsJobMountMountable *job,
+ GMountSpec *mount_spec,
+ const char *filename,
+ gboolean must_mount_location)
+{
+ job->mount_spec = g_mount_spec_ref (mount_spec);
+ job->target_filename = g_strdup (filename);
+ job->must_mount_location = must_mount_location;
+}
+
+void
+g_vfs_job_mount_mountable_set_target_uri (GVfsJobMountMountable *job,
+ const char *uri,
+ gboolean must_mount_location)
+{
+ job->target_uri = g_strdup (uri);
+ job->must_mount_location = must_mount_location;
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->mount_mountable == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->mount_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->mount_source);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_mount_mountable == NULL)
+ return FALSE;
+
+ return class->try_mount_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->mount_source);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ dbus_bool_t must_mount, is_uri;
+
+ reply = dbus_message_new_method_return (message);
+
+ must_mount = op_job->must_mount_location;
+ is_uri = op_job->target_uri != NULL;
+ if (is_uri)
+ {
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &is_uri,
+ G_DBUS_TYPE_CSTRING, &op_job->target_uri,
+ DBUS_TYPE_BOOLEAN, &must_mount,
+ 0);
+ }
+ else
+ {
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &is_uri,
+ G_DBUS_TYPE_CSTRING, &op_job->target_filename,
+ DBUS_TYPE_BOOLEAN, &must_mount,
+ 0);
+ dbus_message_iter_init_append (reply, &iter);
+ g_mount_spec_to_dbus (&iter, op_job->mount_spec);
+ }
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobmountmountable.h b/trunk/daemon/gvfsjobmountmountable.h
new file mode 100644
index 00000000..70968bf0
--- /dev/null
+++ b/trunk/daemon/gvfsjobmountmountable.h
@@ -0,0 +1,76 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_MOUNT_MOUNTABLE_H__
+#define __G_VFS_JOB_MOUNT_MOUNTABLE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MOUNT_MOUNTABLE (g_vfs_job_mount_mountable_get_type ())
+#define G_VFS_JOB_MOUNT_MOUNTABLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MOUNT_MOUNTABLE, GVfsJobMountMountable))
+#define G_VFS_JOB_MOUNT_MOUNTABLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MOUNT_MOUNTABLE, GVfsJobMountMountableClass))
+#define G_VFS_IS_JOB_MOUNT_MOUNTABLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MOUNT_MOUNTABLE))
+#define G_VFS_IS_JOB_MOUNT_MOUNTABLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MOUNT_MOUNTABLE))
+#define G_VFS_JOB_MOUNT_MOUNTABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MOUNT_MOUNTABLE, GVfsJobMountMountableClass))
+
+typedef struct _GVfsJobMountMountableClass GVfsJobMountMountableClass;
+
+struct _GVfsJobMountMountable
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ GMountSource *mount_source;
+
+ char *target_uri;
+ char *target_filename;
+ GMountSpec *mount_spec;
+ gboolean must_mount_location;
+};
+
+struct _GVfsJobMountMountableClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_mount_mountable_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_mount_mountable_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+void g_vfs_job_mount_mountable_set_target (GVfsJobMountMountable *job,
+ GMountSpec *mount_spec,
+ const char *filename,
+ gboolean must_mount_location);
+void g_vfs_job_mount_mountable_set_target_uri (GVfsJobMountMountable *job,
+ const char *uri,
+ gboolean must_mount_location);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MOUNT_MOUNTABLE_H__ */
diff --git a/trunk/daemon/gvfsjobmove.c b/trunk/daemon/gvfsjobmove.c
new file mode 100644
index 00000000..7baa62eb
--- /dev/null
+++ b/trunk/daemon/gvfsjobmove.c
@@ -0,0 +1,210 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmove.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobMove, g_vfs_job_move, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_move_finalize (GObject *object)
+{
+ GVfsJobMove *job;
+
+ job = G_VFS_JOB_MOVE (object);
+
+ g_free (job->source);
+ g_free (job->destination);
+ g_free (job->callback_obj_path);
+
+ if (G_OBJECT_CLASS (g_vfs_job_move_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_move_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_move_class_init (GVfsJobMoveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_move_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_move_init (GVfsJobMove *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_move_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobMove *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path1_len, path2_len;
+ const char *path1_data, *path2_data, *callback_obj_path;
+ dbus_uint32_t flags;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path1_data, &path1_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path2_data, &path2_len,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_MOVE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->source = g_strndup (path1_data, path1_len);
+ job->destination = g_strndup (path2_data, path2_len);
+ job->backend = backend;
+ job->flags = flags;
+ if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
+ job->callback_obj_path = g_strdup (callback_obj_path);
+
+ return G_VFS_JOB (job);
+}
+
+void
+g_vfs_job_move_progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GVfsJob *job)
+{
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ GVfsJobMove *op_job = G_VFS_JOB_MOVE (job);
+ dbus_uint64_t current_dbus, total_dbus;
+ DBusMessage *message;
+
+ g_debug ("progress_callback %d/%d\n", (int)current_num_bytes, (int)total_num_bytes);
+
+ if (op_job->callback_obj_path == NULL)
+ return;
+
+ message =
+ dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
+ op_job->callback_obj_path,
+ G_VFS_DBUS_PROGRESS_INTERFACE,
+ G_VFS_DBUS_PROGRESS_OP_PROGRESS);
+ dbus_message_set_no_reply (message, TRUE);
+
+ current_dbus = current_num_bytes;
+ total_dbus = total_num_bytes;
+ dbus_message_append_args (message,
+ DBUS_TYPE_UINT64, &current_dbus,
+ DBUS_TYPE_UINT64, &total_dbus,
+ 0);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, message, NULL);
+ dbus_message_unref (message);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMove *op_job = G_VFS_JOB_MOVE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->move == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->move (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->destination,
+ op_job->flags,
+ (GFileProgressCallback)g_vfs_job_move_progress_callback,
+ job);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMove *op_job = G_VFS_JOB_MOVE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_move == NULL)
+ return FALSE;
+
+ return class->try_move (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->destination,
+ op_job->flags,
+ (GFileProgressCallback)g_vfs_job_move_progress_callback,
+ job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobmove.h b/trunk/daemon/gvfsjobmove.h
new file mode 100644
index 00000000..d415371e
--- /dev/null
+++ b/trunk/daemon/gvfsjobmove.h
@@ -0,0 +1,71 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_MOVE_H__
+#define __G_VFS_JOB_MOVE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MOVE (g_vfs_job_move_get_type ())
+#define G_VFS_JOB_MOVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MOVE, GVfsJobMove))
+#define G_VFS_JOB_MOVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MOVE, GVfsJobMoveClass))
+#define G_VFS_IS_JOB_MOVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MOVE))
+#define G_VFS_IS_JOB_MOVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MOVE))
+#define G_VFS_JOB_MOVE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MOVE, GVfsJobMoveClass))
+
+typedef struct _GVfsJobMoveClass GVfsJobMoveClass;
+
+struct _GVfsJobMove
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *source;
+ char *destination;
+ GFileCopyFlags flags;
+ char *callback_obj_path;
+
+};
+
+struct _GVfsJobMoveClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_move_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_move_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+void g_vfs_job_move_progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GVfsJob *job);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MOVE_H__ */
diff --git a/trunk/daemon/gvfsjobopenforread.c b/trunk/daemon/gvfsjobopenforread.c
new file mode 100644
index 00000000..0775db46
--- /dev/null
+++ b/trunk/daemon/gvfsjobopenforread.c
@@ -0,0 +1,219 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobopenforread.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void finished (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_open_for_read_finalize (GObject *object)
+{
+ GVfsJobOpenForRead *job;
+
+ job = G_VFS_JOB_OPEN_FOR_READ (object);
+
+ /* TODO: manage backend_handle if not put in read channel */
+
+ if (job->read_channel)
+ g_object_unref (job->read_channel);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_open_for_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_open_for_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_open_for_read_class_init (GVfsJobOpenForReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_open_for_read_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_class->finished = finished;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_open_for_read_init (GVfsJobOpenForRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_open_for_read_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobOpenForRead *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_READ,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobOpenForRead *op_job = G_VFS_JOB_OPEN_FOR_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->open_for_read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->open_for_read (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobOpenForRead *op_job = G_VFS_JOB_OPEN_FOR_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_open_for_read == NULL)
+ return FALSE;
+
+ return class->try_open_for_read (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+
+void
+g_vfs_job_open_for_read_set_handle (GVfsJobOpenForRead *job,
+ GVfsBackendHandle handle)
+{
+ job->backend_handle = handle;
+}
+
+void
+g_vfs_job_open_for_read_set_can_seek (GVfsJobOpenForRead *job,
+ gboolean can_seek)
+{
+ job->can_seek = can_seek;
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobOpenForRead *open_job = G_VFS_JOB_OPEN_FOR_READ (job);
+ GVfsReadChannel *channel;
+ DBusMessage *reply;
+ GError *error;
+ int remote_fd;
+ int fd_id;
+ dbus_bool_t can_seek;
+
+ g_assert (open_job->backend_handle != NULL);
+
+ error = NULL;
+ channel = g_vfs_read_channel_new (open_job->backend);
+
+ remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel));
+ if (!dbus_connection_send_fd (connection,
+ remote_fd,
+ &fd_id, &error))
+ {
+ close (remote_fd);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ g_object_unref (channel);
+ return reply;
+ }
+ close (remote_fd);
+
+ reply = dbus_message_new_method_return (message);
+ can_seek = open_job->can_seek;
+ dbus_message_append_args (reply,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_INVALID);
+
+ g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle);
+ open_job->backend_handle = NULL;
+ open_job->read_channel = channel;
+
+ g_signal_emit_by_name (job, "new-source", open_job->read_channel);
+
+ return reply;
+}
+
+static void
+finished (GVfsJob *job)
+{
+}
diff --git a/trunk/daemon/gvfsjobopenforread.h b/trunk/daemon/gvfsjobopenforread.h
new file mode 100644
index 00000000..a15e2fe8
--- /dev/null
+++ b/trunk/daemon/gvfsjobopenforread.h
@@ -0,0 +1,70 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_OPEN_FOR_READ_H__
+#define __G_VFS_JOB_OPEN_FOR_READ_H__
+
+#include <dbus/dbus.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_OPEN_FOR_READ (g_vfs_job_open_for_read_get_type ())
+#define G_VFS_JOB_OPEN_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_OPEN_FOR_READ, GVfsJobOpenForRead))
+#define G_VFS_JOB_OPEN_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_OPEN_FOR_READ, GVfsJobOpenForReadClass))
+#define G_VFS_IS_JOB_OPEN_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_OPEN_FOR_READ))
+#define G_VFS_IS_JOB_OPEN_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_OPEN_FOR_READ))
+#define G_VFS_JOB_OPEN_FOR_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_OPEN_FOR_READ, GVfsJobOpenForReadClass))
+
+typedef struct _GVfsJobOpenForReadClass GVfsJobOpenForReadClass;
+
+struct _GVfsJobOpenForRead
+{
+ GVfsJobDBus parent_instance;
+
+ char *filename;
+ GVfsBackend *backend;
+ GVfsBackendHandle backend_handle;
+ gboolean can_seek;
+ GVfsReadChannel *read_channel;
+};
+
+struct _GVfsJobOpenForReadClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_open_for_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob * g_vfs_job_open_for_read_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+void g_vfs_job_open_for_read_set_handle (GVfsJobOpenForRead *job,
+ GVfsBackendHandle handle);
+void g_vfs_job_open_for_read_set_can_seek (GVfsJobOpenForRead *job,
+ gboolean can_seek);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_OPEN_FOR_READ_H__ */
diff --git a/trunk/daemon/gvfsjobopenforwrite.c b/trunk/daemon/gvfsjobopenforwrite.c
new file mode 100644
index 00000000..f456f839
--- /dev/null
+++ b/trunk/daemon/gvfsjobopenforwrite.c
@@ -0,0 +1,312 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfswritechannel.h"
+#include "gvfsjobopenforwrite.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobOpenForWrite, g_vfs_job_open_for_write, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void finished (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_open_for_write_finalize (GObject *object)
+{
+ GVfsJobOpenForWrite *job;
+
+ job = G_VFS_JOB_OPEN_FOR_WRITE (object);
+
+ /* TODO: manage backend_handle if not put in write channel */
+
+ if (job->write_channel)
+ g_object_unref (job->write_channel);
+
+ g_free (job->filename);
+ g_free (job->etag);
+
+ if (G_OBJECT_CLASS (g_vfs_job_open_for_write_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_open_for_write_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_open_for_write_class_init (GVfsJobOpenForWriteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_open_for_write_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_class->finished = finished;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_open_for_write_init (GVfsJobOpenForWrite *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_open_for_write_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobOpenForWrite *job;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError derror;
+ char *path;
+ guint16 mode;
+ dbus_bool_t make_backup;
+ const char *etag;
+ guint32 flags;
+
+ path = NULL;
+ dbus_error_init (&derror);
+ dbus_message_iter_init (message, &iter);
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ G_DBUS_TYPE_CSTRING, &path,
+ DBUS_TYPE_UINT16, &mode,
+ DBUS_TYPE_STRING, &etag,
+ DBUS_TYPE_BOOLEAN, &make_backup,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ g_free (path);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_WRITE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = path;
+ job->mode = mode;
+ if (*etag != 0)
+ job->etag = g_strdup (etag);
+ job->make_backup = make_backup;
+ job->flags = flags;
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobOpenForWrite *op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->mode == OPEN_FOR_WRITE_CREATE)
+ {
+ if (class->create == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->create (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else if (op_job->mode == OPEN_FOR_WRITE_APPEND)
+ {
+ if (class->append_to == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->append_to (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else if (op_job->mode == OPEN_FOR_WRITE_REPLACE)
+ {
+ if (class->replace == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->replace (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->etag,
+ op_job->make_backup,
+ op_job->flags);
+ }
+ else
+ g_assert_not_reached (); /* Handled in try */
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobOpenForWrite *op_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->mode == OPEN_FOR_WRITE_CREATE)
+ {
+ if (class->try_create == NULL)
+ return FALSE;
+ return class->try_create (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else if (op_job->mode == OPEN_FOR_WRITE_APPEND)
+ {
+ if (class->try_append_to == NULL)
+ return FALSE;
+ return class->try_append_to (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else if (op_job->mode == OPEN_FOR_WRITE_REPLACE)
+ {
+ if (class->try_replace == NULL)
+ return FALSE;
+ return class->try_replace (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->etag,
+ op_job->make_backup,
+ op_job->flags);
+ }
+ else
+ {
+ GError *error = NULL;
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Wrong open for write type");
+ g_vfs_job_failed_from_error (job, error);
+ g_error_free (error);
+ return TRUE;
+ }
+}
+
+void
+g_vfs_job_open_for_write_set_handle (GVfsJobOpenForWrite *job,
+ GVfsBackendHandle handle)
+{
+ job->backend_handle = handle;
+}
+
+void
+g_vfs_job_open_for_write_set_can_seek (GVfsJobOpenForWrite *job,
+ gboolean can_seek)
+{
+ job->can_seek = can_seek;
+}
+
+void
+g_vfs_job_open_for_write_set_initial_offset (GVfsJobOpenForWrite *job,
+ goffset initial_offset)
+{
+ job->initial_offset = initial_offset;
+}
+
+/* Might be called on an i/o thwrite */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobOpenForWrite *open_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
+ GVfsWriteChannel *channel;
+ DBusMessage *reply;
+ GError *error;
+ int remote_fd;
+ int fd_id;
+ dbus_bool_t can_seek;
+ guint64 initial_offset;
+
+ g_assert (open_job->backend_handle != NULL);
+
+ error = NULL;
+ channel = g_vfs_write_channel_new (open_job->backend);
+
+ remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel));
+ if (!dbus_connection_send_fd (connection,
+ remote_fd,
+ &fd_id, &error))
+ {
+ close (remote_fd);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ g_object_unref (channel);
+ return reply;
+ }
+ close (remote_fd);
+
+ reply = dbus_message_new_method_return (message);
+ can_seek = open_job->can_seek;
+ initial_offset = open_job->initial_offset;
+ dbus_message_append_args (reply,
+ DBUS_TYPE_UINT32, &fd_id,
+ DBUS_TYPE_BOOLEAN, &can_seek,
+ DBUS_TYPE_UINT64, &initial_offset,
+ DBUS_TYPE_INVALID);
+
+ g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle);
+ open_job->backend_handle = NULL;
+ open_job->write_channel = channel;
+
+ g_signal_emit_by_name (job, "new-source", open_job->write_channel);
+
+ return reply;
+}
+
+static void
+finished (GVfsJob *job)
+{
+}
diff --git a/trunk/daemon/gvfsjobopenforwrite.h b/trunk/daemon/gvfsjobopenforwrite.h
new file mode 100644
index 00000000..4f6469d1
--- /dev/null
+++ b/trunk/daemon/gvfsjobopenforwrite.h
@@ -0,0 +1,85 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_OPEN_FOR_WRITE_H__
+#define __G_VFS_JOB_OPEN_FOR_WRITE_H__
+
+#include <dbus/dbus.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+#include <gvfswritechannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_OPEN_FOR_WRITE (g_vfs_job_open_for_write_get_type ())
+#define G_VFS_JOB_OPEN_FOR_WRITE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_OPEN_FOR_WRITE, GVfsJobOpenForWrite))
+#define G_VFS_JOB_OPEN_FOR_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_OPEN_FOR_WRITE, GVfsJobOpenForWriteClass))
+#define G_VFS_IS_JOB_OPEN_FOR_WRITE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_OPEN_FOR_WRITE))
+#define G_VFS_IS_JOB_OPEN_FOR_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_OPEN_FOR_WRITE))
+#define G_VFS_JOB_OPEN_FOR_WRITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_OPEN_FOR_WRITE, GVfsJobOpenForWriteClass))
+
+typedef struct _GVfsJobOpenForWriteClass GVfsJobOpenForWriteClass;
+
+typedef enum {
+ OPEN_FOR_WRITE_CREATE = 0,
+ OPEN_FOR_WRITE_APPEND = 1,
+ OPEN_FOR_WRITE_REPLACE = 2
+} GVfsJobOpenForWriteMode;
+
+struct _GVfsJobOpenForWrite
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsJobOpenForWriteMode mode;
+ char *filename;
+ char *etag;
+ gboolean make_backup;
+ GFileCreateFlags flags;
+
+ GVfsBackend *backend;
+ GVfsBackendHandle backend_handle;
+
+ gboolean can_seek;
+ goffset initial_offset;
+ GVfsWriteChannel *write_channel;
+};
+
+struct _GVfsJobOpenForWriteClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_open_for_write_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_open_for_write_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+void g_vfs_job_open_for_write_set_handle (GVfsJobOpenForWrite *job,
+ GVfsBackendHandle handle);
+void g_vfs_job_open_for_write_set_can_seek (GVfsJobOpenForWrite *job,
+ gboolean can_seek);
+void g_vfs_job_open_for_write_set_initial_offset (GVfsJobOpenForWrite *job,
+ goffset initial_offset);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_OPEN_FOR_WRITE_H__ */
diff --git a/trunk/daemon/gvfsjobopeniconforread.c b/trunk/daemon/gvfsjobopeniconforread.c
new file mode 100644
index 00000000..87936765
--- /dev/null
+++ b/trunk/daemon/gvfsjobopeniconforread.c
@@ -0,0 +1,142 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobopeniconforread.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobOpenIconForRead, g_vfs_job_open_icon_for_read, G_VFS_TYPE_JOB_OPEN_FOR_READ)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+
+static void
+g_vfs_job_open_icon_for_read_finalize (GObject *object)
+{
+ GVfsJobOpenIconForRead *job;
+
+ job = G_VFS_JOB_OPEN_ICON_FOR_READ (object);
+
+ if (G_OBJECT_CLASS (g_vfs_job_open_icon_for_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_open_icon_for_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_open_icon_for_read_class_init (GVfsJobOpenIconForReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_open_icon_for_read_finalize;
+ job_class->run = run;
+ job_class->try = try;
+}
+
+static void
+g_vfs_job_open_icon_for_read_init (GVfsJobOpenIconForRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_open_icon_for_read_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobOpenIconForRead *job;
+ GVfsJobOpenForRead *job_open_for_read;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job);
+
+ job->icon_id = g_strndup (path_data, path_len);
+ job_open_for_read->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobOpenIconForRead *op_job = G_VFS_JOB_OPEN_ICON_FOR_READ (job);
+ GVfsJobOpenForRead *op_job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job_open_for_read->backend);
+
+ if (class->open_icon_for_read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->open_icon_for_read (op_job_open_for_read->backend,
+ op_job,
+ op_job->icon_id);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobOpenIconForRead *op_job = G_VFS_JOB_OPEN_ICON_FOR_READ (job);
+ GVfsJobOpenForRead *op_job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job_open_for_read->backend);
+
+ if (class->try_open_icon_for_read == NULL)
+ return FALSE;
+
+ return class->try_open_icon_for_read (op_job_open_for_read->backend,
+ op_job,
+ op_job->icon_id);
+}
diff --git a/trunk/daemon/gvfsjobopeniconforread.h b/trunk/daemon/gvfsjobopeniconforread.h
new file mode 100644
index 00000000..c4ed80e7
--- /dev/null
+++ b/trunk/daemon/gvfsjobopeniconforread.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_OPEN_ICON_FOR_READ_H__
+#define __G_VFS_JOB_OPEN_ICON_FOR_READ_H__
+
+#include <dbus/dbus.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+#include <gvfsjobopenforread.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ (g_vfs_job_open_icon_for_read_get_type ())
+#define G_VFS_JOB_OPEN_ICON_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForRead))
+#define G_VFS_JOB_OPEN_ICON_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForReadClass))
+#define G_VFS_IS_JOB_OPEN_ICON_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ))
+#define G_VFS_IS_JOB_OPEN_ICON_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ))
+#define G_VFS_JOB_OPEN_ICON_FOR_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForReadClass))
+
+typedef struct _GVfsJobOpenIconForReadClass GVfsJobOpenIconForReadClass;
+
+struct _GVfsJobOpenIconForRead
+{
+ GVfsJobOpenForRead parent_instance;
+
+ char *icon_id;
+};
+
+struct _GVfsJobOpenIconForReadClass
+{
+ GVfsJobOpenForReadClass parent_class;
+};
+
+GType g_vfs_job_open_icon_for_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob * g_vfs_job_open_icon_for_read_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ */
diff --git a/trunk/daemon/gvfsjobpull.c b/trunk/daemon/gvfsjobpull.c
new file mode 100644
index 00000000..58e67afb
--- /dev/null
+++ b/trunk/daemon/gvfsjobpull.c
@@ -0,0 +1,217 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobpull.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobPull, g_vfs_job_pull, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_pull_finalize (GObject *object)
+{
+ GVfsJobPull *job;
+
+ job = G_VFS_JOB_PULL (object);
+
+ g_free (job->local_path);
+ g_free (job->source);
+ g_free (job->callback_obj_path);
+
+ if (G_OBJECT_CLASS (g_vfs_job_pull_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_pull_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_pull_class_init (GVfsJobPullClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_pull_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_pull_init (GVfsJobPull *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_pull_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobPull *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path1_len, path2_len;
+ const char *path1_data, *path2_data, *callback_obj_path;
+ dbus_uint32_t flags;
+ dbus_bool_t remove_source;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path1_data, &path1_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path2_data, &path2_len,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
+ DBUS_TYPE_BOOLEAN, &remove_source,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_PULL,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->source = g_strndup (path1_data, path1_len);
+ job->local_path = g_strndup (path2_data, path2_len);
+ job->backend = backend;
+ job->flags = flags;
+ job->remove_source = remove_source;
+ g_debug ("Remove Source: %s\n", remove_source ? "true" : "false");
+ if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
+ job->callback_obj_path = g_strdup (callback_obj_path);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (user_data);
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ GVfsJobPull *op_job = G_VFS_JOB_PULL (job);
+ dbus_uint64_t current_dbus, total_dbus;
+ DBusMessage *message;
+
+ g_debug ("progress_callback %d/%d\n", (int)current_num_bytes, (int)total_num_bytes);
+
+ if (op_job->callback_obj_path == NULL)
+ return;
+
+ message =
+ dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
+ op_job->callback_obj_path,
+ G_VFS_DBUS_PROGRESS_INTERFACE,
+ G_VFS_DBUS_PROGRESS_OP_PROGRESS);
+ dbus_message_set_no_reply (message, TRUE);
+
+ current_dbus = current_num_bytes;
+ total_dbus = total_num_bytes;
+ dbus_message_append_args (message,
+ DBUS_TYPE_UINT64, &current_dbus,
+ DBUS_TYPE_UINT64, &total_dbus,
+ 0);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, message, NULL);
+ dbus_message_unref (message);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobPull *op_job = G_VFS_JOB_PULL (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->pull == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->pull (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->local_path,
+ op_job->flags,
+ op_job->remove_source,
+ progress_callback,
+ job);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobPull *op_job = G_VFS_JOB_PULL (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_pull == NULL)
+ return FALSE;
+
+ return class->try_pull (op_job->backend,
+ op_job,
+ op_job->source,
+ op_job->local_path,
+ op_job->flags,
+ op_job->remove_source,
+ progress_callback,
+ job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobpull.h b/trunk/daemon/gvfsjobpull.h
new file mode 100644
index 00000000..bb080878
--- /dev/null
+++ b/trunk/daemon/gvfsjobpull.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_PULL_H__
+#define __G_VFS_JOB_PULL_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_PULL (g_vfs_job_pull_get_type ())
+#define G_VFS_JOB_PULL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_PULL, GVfsJobPull))
+#define G_VFS_JOB_PULL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_PULL, GVfsJobPullClass))
+#define G_VFS_IS_JOB_PULL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_PULL))
+#define G_VFS_IS_JOB_PULL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_PULL))
+#define G_VFS_JOB_PULL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_PULL, GVfsJobPullClass))
+
+typedef struct _GVfsJobPullClass GVfsJobPullClass;
+
+struct _GVfsJobPull
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *source;
+ char *local_path;
+ GFileCopyFlags flags;
+ char *callback_obj_path;
+ gboolean remove_source;
+};
+
+struct _GVfsJobPullClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_pull_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_pull_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_PULL_H__ */
diff --git a/trunk/daemon/gvfsjobpush.c b/trunk/daemon/gvfsjobpush.c
new file mode 100644
index 00000000..0ab1efc5
--- /dev/null
+++ b/trunk/daemon/gvfsjobpush.c
@@ -0,0 +1,217 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobpush.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobPush, g_vfs_job_push, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_push_finalize (GObject *object)
+{
+ GVfsJobPush *job;
+
+ job = G_VFS_JOB_PUSH (object);
+
+ g_free (job->local_path);
+ g_free (job->destination);
+ g_free (job->callback_obj_path);
+
+ if (G_OBJECT_CLASS (g_vfs_job_push_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_push_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_push_class_init (GVfsJobPushClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_push_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_push_init (GVfsJobPush *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_push_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobPush *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path1_len, path2_len;
+ const char *path1_data, *path2_data, *callback_obj_path;
+ dbus_uint32_t flags;
+ dbus_bool_t remove_source;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path1_data, &path1_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path2_data, &path2_len,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
+ DBUS_TYPE_BOOLEAN, &remove_source,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_PUSH,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->destination = g_strndup (path1_data, path1_len);
+ job->local_path = g_strndup (path2_data, path2_len);
+ job->backend = backend;
+ job->flags = flags;
+ job->remove_source = remove_source;
+ g_debug ("Remove Source: %s\n", remove_source ? "true" : "false");
+ if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
+ job->callback_obj_path = g_strdup (callback_obj_path);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ GVfsJob *job = G_VFS_JOB (user_data);
+ GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
+ GVfsJobPush *op_job = G_VFS_JOB_PUSH (job);
+ dbus_uint64_t current_dbus, total_dbus;
+ DBusMessage *message;
+
+ g_debug ("progress_callback %d/%d\n", (int)current_num_bytes, (int)total_num_bytes);
+
+ if (op_job->callback_obj_path == NULL)
+ return;
+
+ message =
+ dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
+ op_job->callback_obj_path,
+ G_VFS_DBUS_PROGRESS_INTERFACE,
+ G_VFS_DBUS_PROGRESS_OP_PROGRESS);
+ dbus_message_set_no_reply (message, TRUE);
+
+ current_dbus = current_num_bytes;
+ total_dbus = total_num_bytes;
+ dbus_message_append_args (message,
+ DBUS_TYPE_UINT64, &current_dbus,
+ DBUS_TYPE_UINT64, &total_dbus,
+ 0);
+
+ /* Queues reply (threadsafely), actually sends it in mainloop */
+ dbus_connection_send (dbus_job->connection, message, NULL);
+ dbus_message_unref (message);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobPush *op_job = G_VFS_JOB_PUSH (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->push == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->push (op_job->backend,
+ op_job,
+ op_job->destination,
+ op_job->local_path,
+ op_job->flags,
+ op_job->remove_source,
+ progress_callback,
+ job);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobPush *op_job = G_VFS_JOB_PUSH (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_push == NULL)
+ return FALSE;
+
+ return class->try_push (op_job->backend,
+ op_job,
+ op_job->destination,
+ op_job->local_path,
+ op_job->flags,
+ op_job->remove_source,
+ progress_callback,
+ job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobpush.h b/trunk/daemon/gvfsjobpush.h
new file mode 100644
index 00000000..c7aabcba
--- /dev/null
+++ b/trunk/daemon/gvfsjobpush.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_PUSH_H__
+#define __G_VFS_JOB_PUSH_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_PUSH (g_vfs_job_push_get_type ())
+#define G_VFS_JOB_PUSH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_PUSH, GVfsJobPush))
+#define G_VFS_JOB_PUSH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_PUSH, GVfsJobPushClass))
+#define G_VFS_IS_JOB_PUSH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_PUSH))
+#define G_VFS_IS_JOB_PUSH_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_PUSH))
+#define G_VFS_JOB_PUSH_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_PUSH, GVfsJobPushClass))
+
+typedef struct _GVfsJobPushClass GVfsJobPushClass;
+
+struct _GVfsJobPush
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *destination;
+ char *local_path;
+ GFileCopyFlags flags;
+ char *callback_obj_path;
+ gboolean remove_source;
+};
+
+struct _GVfsJobPushClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_push_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_push_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_PUSH_H__ */
diff --git a/trunk/daemon/gvfsjobqueryattributes.c b/trunk/daemon/gvfsjobqueryattributes.c
new file mode 100644
index 00000000..aeeeafe9
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryattributes.c
@@ -0,0 +1,190 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmove.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobqueryattributes.h"
+
+G_DEFINE_TYPE (GVfsJobQueryAttributes, g_vfs_job_query_attributes, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_query_attributes_finalize (GObject *object)
+{
+ GVfsJobQueryAttributes *job;
+
+ job = G_VFS_JOB_QUERY_ATTRIBUTES (object);
+
+ g_free (job->filename);
+ if (job->list)
+ g_file_attribute_info_list_unref (job->list);
+
+ if (G_OBJECT_CLASS (g_vfs_job_query_attributes_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_query_attributes_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_query_attributes_class_init (GVfsJobQueryAttributesClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_query_attributes_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_query_attributes_init (GVfsJobQueryAttributes *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_query_attributes_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean namespaces)
+{
+ GVfsJobQueryAttributes *job;
+ DBusMessage *reply;
+ DBusError derror;
+ const gchar *path = NULL;
+ gint path_len;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_QUERY_ATTRIBUTES,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->backend = backend;
+ job->filename = g_strndup (path, path_len);
+ job->namespaces = namespaces;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobQueryAttributes *op_job = G_VFS_JOB_QUERY_ATTRIBUTES (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ void (*cb) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+
+ if (op_job->namespaces)
+ cb = class->query_writable_namespaces;
+ else
+ cb = class->query_settable_attributes;
+
+ if (cb == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ cb (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobQueryAttributes *op_job = G_VFS_JOB_QUERY_ATTRIBUTES (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ gboolean (*cb) (GVfsBackend *backend,
+ GVfsJobQueryAttributes *job,
+ const char *filename);
+
+ if (op_job->namespaces)
+ cb = class->try_query_writable_namespaces;
+ else
+ cb = class->try_query_settable_attributes;
+
+ if (cb == NULL)
+ return FALSE;
+
+ return cb (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+void
+g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job,
+ GFileAttributeInfoList *list)
+{
+ job->list = g_file_attribute_info_list_ref (list);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobQueryAttributes *op_job = G_VFS_JOB_QUERY_ATTRIBUTES (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ reply = dbus_message_new_method_return (message);
+
+ dbus_message_iter_init_append (reply, &iter);
+ _g_dbus_append_attribute_info_list (&iter,
+ op_job->list);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobqueryattributes.h b/trunk/daemon/gvfsjobqueryattributes.h
new file mode 100644
index 00000000..33b923a7
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryattributes.h
@@ -0,0 +1,70 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_QUERY_ATTRIBUTES_H__
+#define __G_VFS_JOB_QUERY_ATTRIBUTES_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_QUERY_ATTRIBUTES (g_vfs_job_query_attributes_get_type ())
+#define G_VFS_JOB_QUERY_ATTRIBUTES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_QUERY_ATTRIBUTES, GVfsJobQueryAttributes))
+#define G_VFS_JOB_QUERY_ATTRIBUTES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_QUERY_ATTRIBUTES, GVfsJobQueryAttributesClass))
+#define G_VFS_IS_JOB_QUERY_ATTRIBUTES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_QUERY_ATTRIBUTES))
+#define G_VFS_IS_JOB_QUERY_ATTRIBUTES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_QUERY_ATTRIBUTES))
+#define G_VFS_JOB_QUERY_ATTRIBUTES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_QUERY_ATTRIBUTES, GVfsJobQueryAttributesClass))
+
+typedef struct _GVfsJobQueryAttributesClass GVfsJobQueryAttributesClass;
+
+struct _GVfsJobQueryAttributes
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+
+ char *filename;
+ gboolean namespaces;
+
+ GFileAttributeInfoList *list;
+};
+
+struct _GVfsJobQueryAttributesClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_query_attributes_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_query_attributes_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean namespaces);
+void g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job,
+ GFileAttributeInfoList *list);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_QUERY_ATTRIBUTES_H__ */
diff --git a/trunk/daemon/gvfsjobqueryfsinfo.c b/trunk/daemon/gvfsjobqueryfsinfo.c
new file mode 100644
index 00000000..a5d369c4
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryfsinfo.c
@@ -0,0 +1,184 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobqueryfsinfo.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobQueryFsInfo, g_vfs_job_query_fs_info, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_query_fs_info_finalize (GObject *object)
+{
+ GVfsJobQueryFsInfo *job;
+
+ job = G_VFS_JOB_QUERY_FS_INFO (object);
+
+ g_object_unref (job->file_info);
+
+ g_free (job->filename);
+ g_file_attribute_matcher_unref (job->attribute_matcher);
+
+ if (G_OBJECT_CLASS (g_vfs_job_query_fs_info_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_query_fs_info_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_query_fs_info_class_init (GVfsJobQueryFsInfoClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_query_fs_info_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_query_fs_info_init (GVfsJobQueryFsInfo *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_query_fs_info_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobQueryFsInfo *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+ char *attributes;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ DBUS_TYPE_STRING, &attributes,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_QUERY_FS_INFO,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+ job->attribute_matcher = g_file_attribute_matcher_new (attributes);
+
+ job->file_info = g_file_info_new ();
+ g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->query_fs_info == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->query_fs_info (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_query_fs_info == NULL)
+ return FALSE;
+
+ return class->try_query_fs_info (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ const char *type;
+
+ reply = dbus_message_new_method_return (message);
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ type = g_vfs_backend_get_backend_type (op_job->backend);
+
+ if (type)
+ g_file_info_set_attribute_string (op_job->file_info,
+ G_FILE_ATTRIBUTE_GVFS_BACKEND,
+ type);
+
+ _g_dbus_append_file_info (&iter,
+ op_job->file_info);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobqueryfsinfo.h b/trunk/daemon/gvfsjobqueryfsinfo.h
new file mode 100644
index 00000000..c273fee5
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryfsinfo.h
@@ -0,0 +1,66 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_QUERY_FS_INFO_H__
+#define __G_VFS_JOB_QUERY_FS_INFO_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_QUERY_FS_INFO (g_vfs_job_query_fs_info_get_type ())
+#define G_VFS_JOB_QUERY_FS_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_QUERY_FS_INFO, GVfsJobQueryFsInfo))
+#define G_VFS_JOB_QUERY_FS_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_QUERY_FS_INFO, GVfsJobQueryFsInfoClass))
+#define G_VFS_IS_JOB_QUERY_FS_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_QUERY_FS_INFO))
+#define G_VFS_IS_JOB_QUERY_FS_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_QUERY_FS_INFO))
+#define G_VFS_JOB_QUERY_FS_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_QUERY_FS_INFO, GVfsJobQueryFsInfoClass))
+
+typedef struct _GVfsJobQueryFsInfoClass GVfsJobQueryFsInfoClass;
+
+struct _GVfsJobQueryFsInfo
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ GFileAttributeMatcher *attribute_matcher;
+
+ GFileInfo *file_info;
+};
+
+struct _GVfsJobQueryFsInfoClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_query_fs_info_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_query_fs_info_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_QUERY_FS_INFO_H__ */
diff --git a/trunk/daemon/gvfsjobqueryinfo.c b/trunk/daemon/gvfsjobqueryinfo.c
new file mode 100644
index 00000000..78bf1607
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinfo.c
@@ -0,0 +1,201 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobqueryinfo.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobQueryInfo, g_vfs_job_query_info, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_query_info_finalize (GObject *object)
+{
+ GVfsJobQueryInfo *job;
+
+ job = G_VFS_JOB_QUERY_INFO (object);
+
+ g_object_unref (job->file_info);
+
+ g_free (job->filename);
+ g_free (job->attributes);
+ g_file_attribute_matcher_unref (job->attribute_matcher);
+ g_free (job->uri);
+
+ if (G_OBJECT_CLASS (g_vfs_job_query_info_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_query_info_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_query_info_class_init (GVfsJobQueryInfoClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_query_info_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_query_info_init (GVfsJobQueryInfo *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_query_info_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobQueryInfo *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+ char *attributes;
+ char *uri;
+ dbus_uint32_t flags;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&derror);
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ DBUS_TYPE_STRING, &attributes,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ /* Optional uri arg for thumbnail info */
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_STRING, &uri,
+ 0))
+ uri = NULL;
+
+ job = g_object_new (G_VFS_TYPE_JOB_QUERY_INFO,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+ job->attributes = g_strdup (attributes);
+ job->attribute_matcher = g_file_attribute_matcher_new (attributes);
+ job->flags = flags;
+ job->uri = g_strdup (uri);
+
+ job->file_info = g_file_info_new ();
+ g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobQueryInfo *op_job = G_VFS_JOB_QUERY_INFO (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->query_info == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->query_info (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobQueryInfo *op_job = G_VFS_JOB_QUERY_INFO (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_query_info == NULL)
+ return FALSE;
+
+ return class->try_query_info (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobQueryInfo *op_job = G_VFS_JOB_QUERY_INFO (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ reply = dbus_message_new_method_return (message);
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ g_vfs_backend_add_auto_info (op_job->backend,
+ op_job->attribute_matcher,
+ op_job->file_info,
+ op_job->uri);
+
+ _g_dbus_append_file_info (&iter,
+ op_job->file_info);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobqueryinfo.h b/trunk/daemon/gvfsjobqueryinfo.h
new file mode 100644
index 00000000..4a6b5d88
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinfo.h
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_QUERY_INFO_H__
+#define __G_VFS_JOB_QUERY_INFO_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_QUERY_INFO (g_vfs_job_query_info_get_type ())
+#define G_VFS_JOB_QUERY_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_QUERY_INFO, GVfsJobQueryInfo))
+#define G_VFS_JOB_QUERY_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_QUERY_INFO, GVfsJobQueryInfoClass))
+#define G_VFS_IS_JOB_QUERY_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_QUERY_INFO))
+#define G_VFS_IS_JOB_QUERY_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_QUERY_INFO))
+#define G_VFS_JOB_QUERY_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_QUERY_INFO, GVfsJobQueryInfoClass))
+
+typedef struct _GVfsJobQueryInfoClass GVfsJobQueryInfoClass;
+
+struct _GVfsJobQueryInfo
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ char *attributes;
+ GFileAttributeMatcher *attribute_matcher;
+ GFileQueryInfoFlags flags;
+ char *uri;
+
+ GFileInfo *file_info;
+};
+
+struct _GVfsJobQueryInfoClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_query_info_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_query_info_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_QUERY_INFO_H__ */
diff --git a/trunk/daemon/gvfsjobqueryinforead.c b/trunk/daemon/gvfsjobqueryinforead.c
new file mode 100644
index 00000000..7d8453a9
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinforead.c
@@ -0,0 +1,144 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobqueryinforead.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobQueryInfoRead, g_vfs_job_query_info_read, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_query_info_read_finalize (GObject *object)
+{
+ GVfsJobQueryInfoRead *job;
+
+ job = G_VFS_JOB_QUERY_INFO_READ (object);
+ g_object_unref (job->channel);
+ g_object_unref (job->file_info);
+ g_free (job->attributes);
+ g_file_attribute_matcher_unref (job->attribute_matcher);
+
+ if (G_OBJECT_CLASS (g_vfs_job_query_info_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_query_info_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_query_info_read_class_init (GVfsJobQueryInfoReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_query_info_read_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_query_info_read_init (GVfsJobQueryInfoRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_query_info_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ const char *attrs,
+ GVfsBackend *backend)
+{
+ GVfsJobQueryInfoRead *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_QUERY_INFO_READ,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ job->attributes = g_strdup (attrs);
+ job->attribute_matcher = g_file_attribute_matcher_new (attrs);
+
+ job->file_info = g_file_info_new ();
+ g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobQueryInfoRead *op_job = G_VFS_JOB_QUERY_INFO_READ (job);
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ g_vfs_channel_send_info (G_VFS_CHANNEL (op_job->channel), op_job->file_info);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobQueryInfoRead *op_job = G_VFS_JOB_QUERY_INFO_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->query_info_on_read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->query_info_on_read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobQueryInfoRead *op_job = G_VFS_JOB_QUERY_INFO_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_query_info_on_read == NULL)
+ return FALSE;
+
+ return class->try_query_info_on_read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
diff --git a/trunk/daemon/gvfsjobqueryinforead.h b/trunk/daemon/gvfsjobqueryinforead.h
new file mode 100644
index 00000000..1fdfe4d1
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinforead.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_QUERY_INFO_READ_H__
+#define __G_VFS_JOB_QUERY_INFO_READ_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_QUERY_INFO_READ (g_vfs_job_query_info_read_get_type ())
+#define G_VFS_JOB_QUERY_INFO_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_QUERY_INFO_READ, GVfsJobQueryInfoRead))
+#define G_VFS_JOB_QUERY_INFO_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_QUERY_INFO_READ, GVfsJobQueryInfoReadClass))
+#define G_VFS_IS_JOB_QUERY_INFO_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_QUERY_INFO_READ))
+#define G_VFS_IS_JOB_QUERY_INFO_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_QUERY_INFO_READ))
+#define G_VFS_JOB_QUERY_INFO_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_QUERY_INFO_READ, GVfsJobQueryInfoReadClass))
+
+typedef struct _GVfsJobQueryInfoReadClass GVfsJobQueryInfoReadClass;
+
+struct _GVfsJobQueryInfoRead
+{
+ GVfsJob parent_instance;
+
+ GVfsReadChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ char *attributes;
+ GFileAttributeMatcher *attribute_matcher;
+
+ GFileInfo *file_info;
+};
+
+struct _GVfsJobQueryInfoReadClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_query_info_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_query_info_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ const char *attrs,
+ GVfsBackend *backend);
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_QUERY_INFO_READ_H__ */
diff --git a/trunk/daemon/gvfsjobqueryinfowrite.c b/trunk/daemon/gvfsjobqueryinfowrite.c
new file mode 100644
index 00000000..7b454f35
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinfowrite.c
@@ -0,0 +1,144 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfswritechannel.h"
+#include "gvfsjobqueryinfowrite.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobQueryInfoWrite, g_vfs_job_query_info_write, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_query_info_write_finalize (GObject *object)
+{
+ GVfsJobQueryInfoWrite *job;
+
+ job = G_VFS_JOB_QUERY_INFO_WRITE (object);
+ g_object_unref (job->channel);
+ g_object_unref (job->file_info);
+ g_free (job->attributes);
+ g_file_attribute_matcher_unref (job->attribute_matcher);
+
+ if (G_OBJECT_CLASS (g_vfs_job_query_info_write_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_query_info_write_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_query_info_write_class_init (GVfsJobQueryInfoWriteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_query_info_write_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_query_info_write_init (GVfsJobQueryInfoWrite *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_query_info_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ const char *attrs,
+ GVfsBackend *backend)
+{
+ GVfsJobQueryInfoWrite *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_QUERY_INFO_WRITE,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ job->attributes = g_strdup (attrs);
+ job->attribute_matcher = g_file_attribute_matcher_new (attrs);
+
+ job->file_info = g_file_info_new ();
+ g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thwrite */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobQueryInfoWrite *op_job = G_VFS_JOB_QUERY_INFO_WRITE (job);
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ g_vfs_channel_send_info (G_VFS_CHANNEL (op_job->channel), op_job->file_info);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobQueryInfoWrite *op_job = G_VFS_JOB_QUERY_INFO_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->query_info_on_write == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->query_info_on_write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobQueryInfoWrite *op_job = G_VFS_JOB_QUERY_INFO_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_query_info_on_write == NULL)
+ return FALSE;
+
+ return class->try_query_info_on_write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->file_info,
+ op_job->attribute_matcher);
+}
diff --git a/trunk/daemon/gvfsjobqueryinfowrite.h b/trunk/daemon/gvfsjobqueryinfowrite.h
new file mode 100644
index 00000000..1a2ac4cf
--- /dev/null
+++ b/trunk/daemon/gvfsjobqueryinfowrite.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_QUERY_INFO_WRITE_H__
+#define __G_VFS_JOB_QUERY_INFO_WRITE_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfswritechannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_QUERY_INFO_WRITE (g_vfs_job_query_info_write_get_type ())
+#define G_VFS_JOB_QUERY_INFO_WRITE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_QUERY_INFO_WRITE, GVfsJobQueryInfoWrite))
+#define G_VFS_JOB_QUERY_INFO_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_QUERY_INFO_WRITE, GVfsJobQueryInfoWriteClass))
+#define G_VFS_IS_JOB_QUERY_INFO_WRITE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_QUERY_INFO_WRITE))
+#define G_VFS_IS_JOB_QUERY_INFO_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_QUERY_INFO_WRITE))
+#define G_VFS_JOB_QUERY_INFO_WRITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_QUERY_INFO_WRITE, GVfsJobQueryInfoWriteClass))
+
+typedef struct _GVfsJobQueryInfoWriteClass GVfsJobQueryInfoWriteClass;
+
+struct _GVfsJobQueryInfoWrite
+{
+ GVfsJob parent_instance;
+
+ GVfsWriteChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ char *attributes;
+ GFileAttributeMatcher *attribute_matcher;
+
+ GFileInfo *file_info;
+};
+
+struct _GVfsJobQueryInfoWriteClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_query_info_write_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_query_info_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ const char *attrs,
+ GVfsBackend *backend);
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_QUERY_INFO_WRITE_H__ */
diff --git a/trunk/daemon/gvfsjobread.c b/trunk/daemon/gvfsjobread.c
new file mode 100644
index 00000000..0e118674
--- /dev/null
+++ b/trunk/daemon/gvfsjobread.c
@@ -0,0 +1,154 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobread.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobRead, g_vfs_job_read, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_read_finalize (GObject *object)
+{
+ GVfsJobRead *job;
+
+ job = G_VFS_JOB_READ (object);
+
+ g_object_unref (job->channel);
+ g_free (job->buffer);
+
+ if (G_OBJECT_CLASS (g_vfs_job_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_read_class_init (GVfsJobReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_read_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_read_init (GVfsJobRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ gsize bytes_requested,
+ GVfsBackend *backend)
+{
+ GVfsJobRead *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_READ,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ job->buffer = g_malloc (bytes_requested);
+ job->bytes_requested = bytes_requested;
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobRead *op_job = G_VFS_JOB_READ (job);
+ g_debug ("job_read send reply, %"G_GSIZE_FORMAT" bytes\n", op_job->data_count);
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ {
+ g_vfs_read_channel_send_data (op_job->channel,
+ op_job->buffer,
+ op_job->data_count);
+ }
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobRead *op_job = G_VFS_JOB_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->buffer,
+ op_job->bytes_requested);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobRead *op_job = G_VFS_JOB_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_read == NULL)
+ return FALSE;
+
+ return class->try_read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->buffer,
+ op_job->bytes_requested);
+}
+
+
+/* Takes ownership */
+void
+g_vfs_job_read_set_size (GVfsJobRead *job,
+ gsize data_size)
+{
+ job->data_count = data_size;
+}
diff --git a/trunk/daemon/gvfsjobread.h b/trunk/daemon/gvfsjobread.h
new file mode 100644
index 00000000..212cf737
--- /dev/null
+++ b/trunk/daemon/gvfsjobread.h
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_READ_H__
+#define __G_VFS_JOB_READ_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_READ (g_vfs_job_read_get_type ())
+#define G_VFS_JOB_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_READ, GVfsJobRead))
+#define G_VFS_JOB_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_READ, GVfsJobReadClass))
+#define G_VFS_IS_JOB_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_READ))
+#define G_VFS_IS_JOB_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_READ))
+#define G_VFS_JOB_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_READ, GVfsJobReadClass))
+
+typedef struct _GVfsJobReadClass GVfsJobReadClass;
+
+struct _GVfsJobRead
+{
+ GVfsJob parent_instance;
+
+ GVfsReadChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ gsize bytes_requested;
+ char *buffer;
+ gsize data_count;
+};
+
+struct _GVfsJobReadClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ gsize bytes_requested,
+ GVfsBackend *backend);
+void g_vfs_job_read_set_size (GVfsJobRead *job,
+ gsize data_size);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_READ_H__ */
diff --git a/trunk/daemon/gvfsjobseekread.c b/trunk/daemon/gvfsjobseekread.c
new file mode 100644
index 00000000..e886a13d
--- /dev/null
+++ b/trunk/daemon/gvfsjobseekread.c
@@ -0,0 +1,151 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfsreadchannel.h"
+#include "gvfsjobseekread.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobSeekRead, g_vfs_job_seek_read, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_seek_read_finalize (GObject *object)
+{
+ GVfsJobSeekRead *job;
+
+ job = G_VFS_JOB_SEEK_READ (object);
+ g_object_unref (job->channel);
+
+ if (G_OBJECT_CLASS (g_vfs_job_seek_read_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_seek_read_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_seek_read_class_init (GVfsJobSeekReadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_seek_read_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_seek_read_init (GVfsJobSeekRead *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_seek_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ GSeekType seek_type,
+ goffset offset,
+ GVfsBackend *backend)
+{
+ GVfsJobSeekRead *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_SEEK_READ,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ job->requested_offset = offset;
+ job->seek_type = seek_type;
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobSeekRead *op_job = G_VFS_JOB_SEEK_READ (job);
+
+ g_debug ("job_seek_read send reply, pos %d\n", (int)op_job->final_offset);
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ {
+ g_vfs_read_channel_send_seek_offset (op_job->channel,
+ op_job->final_offset);
+ }
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobSeekRead *op_job = G_VFS_JOB_SEEK_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->seek_on_read == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->seek_on_read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->requested_offset,
+ op_job->seek_type);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobSeekRead *op_job = G_VFS_JOB_SEEK_READ (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_seek_on_read == NULL)
+ return FALSE;
+
+ return class->try_seek_on_read (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->requested_offset,
+ op_job->seek_type);
+}
+
+void
+g_vfs_job_seek_read_set_offset (GVfsJobSeekRead *job,
+ goffset offset)
+{
+ job->final_offset = offset;
+}
diff --git a/trunk/daemon/gvfsjobseekread.h b/trunk/daemon/gvfsjobseekread.h
new file mode 100644
index 00000000..7b23d29f
--- /dev/null
+++ b/trunk/daemon/gvfsjobseekread.h
@@ -0,0 +1,72 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_SEEK_READ_H__
+#define __G_VFS_JOB_SEEK_READ_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfsreadchannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SEEK_READ (g_vfs_job_seek_read_get_type ())
+#define G_VFS_JOB_SEEK_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SEEK_READ, GVfsJobSeekRead))
+#define G_VFS_JOB_SEEK_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SEEK_READ, GVfsJobSeekReadClass))
+#define G_VFS_IS_JOB_SEEK_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SEEK_READ))
+#define G_VFS_IS_JOB_SEEK_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SEEK_READ))
+#define G_VFS_JOB_SEEK_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SEEK_READ, GVfsJobSeekReadClass))
+
+typedef struct _GVfsJobSeekReadClass GVfsJobSeekReadClass;
+
+struct _GVfsJobSeekRead
+{
+ GVfsJob parent_instance;
+
+ GVfsReadChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ GSeekType seek_type;
+ goffset requested_offset;
+ goffset final_offset;
+};
+
+struct _GVfsJobSeekReadClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_seek_read_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_seek_read_new (GVfsReadChannel *channel,
+ GVfsBackendHandle handle,
+ GSeekType seek_type,
+ goffset offset,
+ GVfsBackend *backend);
+
+void g_vfs_job_seek_read_set_offset (GVfsJobSeekRead *job,
+ goffset offset);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SEEK_READ_H__ */
diff --git a/trunk/daemon/gvfsjobseekwrite.c b/trunk/daemon/gvfsjobseekwrite.c
new file mode 100644
index 00000000..b2810bc4
--- /dev/null
+++ b/trunk/daemon/gvfsjobseekwrite.c
@@ -0,0 +1,151 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfswritechannel.h"
+#include "gvfsjobseekwrite.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobSeekWrite, g_vfs_job_seek_write, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_seek_write_finalize (GObject *object)
+{
+ GVfsJobSeekWrite *job;
+
+ job = G_VFS_JOB_SEEK_WRITE (object);
+ g_object_unref (job->channel);
+
+ if (G_OBJECT_CLASS (g_vfs_job_seek_write_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_seek_write_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_seek_write_class_init (GVfsJobSeekWriteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_seek_write_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_seek_write_init (GVfsJobSeekWrite *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_seek_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ GSeekType seek_type,
+ goffset offset,
+ GVfsBackend *backend)
+{
+ GVfsJobSeekWrite *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_SEEK_WRITE,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ job->requested_offset = offset;
+ job->seek_type = seek_type;
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thwrite */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobSeekWrite *op_job = G_VFS_JOB_SEEK_WRITE (job);
+
+ g_debug ("job_seek_write send reply, pos %d\n", (int)op_job->final_offset);
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ {
+ g_vfs_write_channel_send_seek_offset (op_job->channel,
+ op_job->final_offset);
+ }
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobSeekWrite *op_job = G_VFS_JOB_SEEK_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->seek_on_write == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->seek_on_write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->requested_offset,
+ op_job->seek_type);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobSeekWrite *op_job = G_VFS_JOB_SEEK_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_seek_on_write == NULL)
+ return FALSE;
+
+ return class->try_seek_on_write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->requested_offset,
+ op_job->seek_type);
+}
+
+void
+g_vfs_job_seek_write_set_offset (GVfsJobSeekWrite *job,
+ goffset offset)
+{
+ job->final_offset = offset;
+}
diff --git a/trunk/daemon/gvfsjobseekwrite.h b/trunk/daemon/gvfsjobseekwrite.h
new file mode 100644
index 00000000..5e0756fb
--- /dev/null
+++ b/trunk/daemon/gvfsjobseekwrite.h
@@ -0,0 +1,71 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_SEEK_WRITE_H__
+#define __G_VFS_JOB_SEEK_WRITE_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfswritechannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SEEK_WRITE (g_vfs_job_seek_write_get_type ())
+#define G_VFS_JOB_SEEK_WRITE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SEEK_WRITE, GVfsJobSeekWrite))
+#define G_VFS_JOB_SEEK_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SEEK_WRITE, GVfsJobSeekWriteClass))
+#define G_VFS_IS_JOB_SEEK_WRITE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SEEK_WRITE))
+#define G_VFS_IS_JOB_SEEK_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SEEK_WRITE))
+#define G_VFS_JOB_SEEK_WRITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SEEK_WRITE, GVfsJobSeekWriteClass))
+
+typedef struct _GVfsJobSeekWriteClass GVfsJobSeekWriteClass;
+
+struct _GVfsJobSeekWrite
+{
+ GVfsJob parent_instance;
+
+ GVfsWriteChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ GSeekType seek_type;
+ goffset requested_offset;
+ goffset final_offset;
+};
+
+struct _GVfsJobSeekWriteClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_seek_write_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_seek_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ GSeekType seek_type,
+ goffset offset,
+ GVfsBackend *backend);
+void g_vfs_job_seek_write_set_offset (GVfsJobSeekWrite *job,
+ goffset offset);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SEEK_WRITE_H__ */
diff --git a/trunk/daemon/gvfsjobsetattribute.c b/trunk/daemon/gvfsjobsetattribute.c
new file mode 100644
index 00000000..3904a3f2
--- /dev/null
+++ b/trunk/daemon/gvfsjobsetattribute.c
@@ -0,0 +1,192 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmove.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobsetattribute.h"
+
+G_DEFINE_TYPE (GVfsJobSetAttribute, g_vfs_job_set_attribute, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_set_attribute_finalize (GObject *object)
+{
+ GVfsJobSetAttribute *job;
+
+ job = G_VFS_JOB_SET_ATTRIBUTE (object);
+
+ g_free (job->filename);
+ g_free (job->attribute);
+ _g_dbus_attribute_value_destroy (job->type,
+ &job->value);
+
+ if (G_OBJECT_CLASS (g_vfs_job_set_attribute_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_set_attribute_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_set_attribute_class_init (GVfsJobSetAttributeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_set_attribute_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_set_attribute_init (GVfsJobSetAttribute *job)
+{
+ job->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
+}
+
+GVfsJob *
+g_vfs_job_set_attribute_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobSetAttribute *job;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ const gchar *filename = NULL;
+ gint filename_len;
+ GFileQueryInfoFlags flags;
+ gchar *attribute;
+ dbus_uint32_t flags_u32 = 0;
+ GFileAttributeType type;
+ GDbusAttributeValue value;
+
+ dbus_message_iter_init (message, &iter);
+
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY &&
+ dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_BYTE)
+ {
+ dbus_message_iter_recurse (&iter, &array_iter);
+ dbus_message_iter_get_fixed_array (&array_iter, &filename, &filename_len);
+ }
+
+ dbus_message_iter_next (&iter);
+
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&iter, &flags_u32);
+ dbus_message_iter_next (&iter);
+ }
+
+ flags = flags_u32;
+
+ if (!(filename && _g_dbus_get_file_attribute (&iter, &attribute, &type, &value)))
+ {
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_FAILED,
+ _("Invalid dbus message"));
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_SET_ATTRIBUTE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->backend = backend;
+ job->filename = g_strndup (filename, filename_len);
+ job->attribute = attribute;
+ job->value = value;
+ job->type = type;
+ job->flags = flags;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobSetAttribute *op_job = G_VFS_JOB_SET_ATTRIBUTE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->set_attribute == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->set_attribute (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute,
+ op_job->type,
+ _g_dbus_attribute_as_pointer (op_job->type, &op_job->value),
+ op_job->flags);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobSetAttribute *op_job = G_VFS_JOB_SET_ATTRIBUTE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_set_attribute == NULL)
+ return FALSE;
+
+ return class->try_set_attribute (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute,
+ op_job->type,
+ _g_dbus_attribute_as_pointer (op_job->type, &op_job->value),
+ op_job->flags);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobsetattribute.h b/trunk/daemon/gvfsjobsetattribute.h
new file mode 100644
index 00000000..72585151
--- /dev/null
+++ b/trunk/daemon/gvfsjobsetattribute.h
@@ -0,0 +1,68 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_SET_ATTRIBUTE_H__
+#define __G_VFS_JOB_SET_ATTRIBUTE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SET_ATTRIBUTE (g_vfs_job_set_attribute_get_type ())
+#define G_VFS_JOB_SET_ATTRIBUTE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttribute))
+#define G_VFS_JOB_SET_ATTRIBUTE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttributeClass))
+#define G_VFS_IS_JOB_SET_ATTRIBUTE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE))
+#define G_VFS_IS_JOB_SET_ATTRIBUTE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SET_ATTRIBUTE))
+#define G_VFS_JOB_SET_ATTRIBUTE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttributeClass))
+
+typedef struct _GVfsJobSetAttributeClass GVfsJobSetAttributeClass;
+
+struct _GVfsJobSetAttribute
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+
+ char *filename;
+ char *attribute;
+ GFileAttributeType type;
+ GDbusAttributeValue value;
+ GFileQueryInfoFlags flags;
+};
+
+struct _GVfsJobSetAttributeClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_set_attribute_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_set_attribute_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SET_ATTRIBUTE_H__ */
diff --git a/trunk/daemon/gvfsjobsetdisplayname.c b/trunk/daemon/gvfsjobsetdisplayname.c
new file mode 100644
index 00000000..e3dd22db
--- /dev/null
+++ b/trunk/daemon/gvfsjobsetdisplayname.c
@@ -0,0 +1,178 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobsetdisplayname.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobSetDisplayName, g_vfs_job_set_display_name, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_set_display_name_finalize (GObject *object)
+{
+ GVfsJobSetDisplayName *job;
+
+ job = G_VFS_JOB_SET_DISPLAY_NAME (object);
+
+ g_free (job->filename);
+ g_free (job->display_name);
+ g_free (job->new_path);
+
+ if (G_OBJECT_CLASS (g_vfs_job_set_display_name_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_set_display_name_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_set_display_name_class_init (GVfsJobSetDisplayNameClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_set_display_name_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_set_display_name_init (GVfsJobSetDisplayName *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_set_display_name_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobSetDisplayName *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+ char *display_name;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ DBUS_TYPE_STRING, &display_name,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_SET_DISPLAY_NAME,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+ job->display_name = g_strdup (display_name);
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->set_display_name == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->set_display_name (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->display_name);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_set_display_name == NULL)
+ return FALSE;
+
+ return class->try_set_display_name (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->display_name);
+}
+
+void
+g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job,
+ const char *new_path)
+{
+ job->new_path = g_strdup (new_path);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job);
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ reply = dbus_message_new_method_return (message);
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ g_assert (op_job->new_path != NULL);
+
+ _g_dbus_message_iter_append_cstring (&iter, op_job->new_path);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobsetdisplayname.h b/trunk/daemon/gvfsjobsetdisplayname.h
new file mode 100644
index 00000000..9e773f46
--- /dev/null
+++ b/trunk/daemon/gvfsjobsetdisplayname.h
@@ -0,0 +1,68 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_SET_DISPLAY_NAME_H__
+#define __G_VFS_JOB_SET_DISPLAY_NAME_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SET_DISPLAY_NAME (g_vfs_job_set_display_name_get_type ())
+#define G_VFS_JOB_SET_DISPLAY_NAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SET_DISPLAY_NAME, GVfsJobSetDisplayName))
+#define G_VFS_JOB_SET_DISPLAY_NAME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SET_DISPLAY_NAME, GVfsJobSetDisplayNameClass))
+#define G_VFS_IS_JOB_SET_DISPLAY_NAME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SET_DISPLAY_NAME))
+#define G_VFS_IS_JOB_SET_DISPLAY_NAME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SET_DISPLAY_NAME))
+#define G_VFS_JOB_SET_DISPLAY_NAME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SET_DISPLAY_NAME, GVfsJobSetDisplayNameClass))
+
+typedef struct _GVfsJobSetDisplayNameClass GVfsJobSetDisplayNameClass;
+
+struct _GVfsJobSetDisplayName
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ char *display_name;
+
+ char *new_path;
+};
+
+struct _GVfsJobSetDisplayNameClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_set_display_name_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_set_display_name_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+void g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job,
+ const char *new_path);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SET_DISPLAY_NAME_H__ */
diff --git a/trunk/daemon/gvfsjobsource.c b/trunk/daemon/gvfsjobsource.c
new file mode 100644
index 00000000..f0feda30
--- /dev/null
+++ b/trunk/daemon/gvfsjobsource.c
@@ -0,0 +1,107 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+#include "gvfsjobsource.h"
+
+static void g_vfs_job_source_base_init (gpointer g_class);
+
+enum {
+ NEW_JOB,
+ CLOSED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+GType
+g_vfs_job_source_get_type (void)
+{
+ static GType vfs_job_source_type = 0;
+
+ if (! vfs_job_source_type)
+ {
+ static const GTypeInfo vfs_job_source_info =
+ {
+ sizeof (GVfsJobSourceIface), /* class_size */
+ g_vfs_job_source_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL
+ };
+
+ vfs_job_source_type =
+ g_type_register_static (G_TYPE_INTERFACE, "GVfsJobSource",
+ &vfs_job_source_info, 0);
+
+ g_type_interface_add_prerequisite (vfs_job_source_type, G_TYPE_OBJECT);
+ }
+
+ return vfs_job_source_type;
+}
+
+
+static void
+g_vfs_job_source_base_init (gpointer g_class)
+{
+ static gboolean initialized = FALSE;
+
+ if (! initialized)
+ {
+ initialized = TRUE;
+
+ signals[NEW_JOB] =
+ g_signal_new ("new_job",
+ G_VFS_TYPE_JOB_SOURCE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsJobSourceIface, new_job),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_VFS_TYPE_JOB);
+
+ signals[CLOSED] =
+ g_signal_new ("closed",
+ G_VFS_TYPE_JOB_SOURCE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GVfsJobSourceIface, closed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ }
+}
+
+void
+g_vfs_job_source_new_job (GVfsJobSource *job_source,
+ GVfsJob *job)
+{
+ g_signal_emit (job_source, signals[NEW_JOB], 0, job);
+}
+
+void
+g_vfs_job_source_closed (GVfsJobSource *job_source)
+{
+ g_signal_emit (job_source, signals[CLOSED], 0);
+}
diff --git a/trunk/daemon/gvfsjobsource.h b/trunk/daemon/gvfsjobsource.h
new file mode 100644
index 00000000..0740d48c
--- /dev/null
+++ b/trunk/daemon/gvfsjobsource.h
@@ -0,0 +1,62 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_SOURCE_H__
+#define __G_VFS_JOB_SOURCE_H__
+
+#include <glib-object.h>
+#include <gvfsjob.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SOURCE (g_vfs_job_source_get_type ())
+#define G_VFS_JOB_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_VFS_TYPE_JOB_SOURCE, GVfsJobSource))
+#define G_VFS_IS_JOB_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_VFS_TYPE_JOB_SOURCE))
+#define G_VFS_JOB_SOURCE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_VFS_TYPE_JOB_SOURCE, GVfsJobSourceIface))
+
+/* GVfsJobSource defined in gvfsjob.h */
+typedef struct _GVfsJobSourceIface GVfsJobSourceIface;
+
+struct _GVfsJobSourceIface
+{
+ GTypeInterface g_iface;
+
+ /* Virtual Table: */
+
+ /* Signals: */
+
+ void (*new_job) (GVfsJobSource *source,
+ GVfsJob *job);
+ void (*closed) (GVfsJobSource *source);
+
+};
+
+GType g_vfs_job_source_get_type (void) G_GNUC_CONST;
+
+void g_vfs_job_source_new_job (GVfsJobSource *job_source,
+ GVfsJob *job);
+void g_vfs_job_source_closed (GVfsJobSource *job_source);
+
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SOURCE_H__ */
diff --git a/trunk/daemon/gvfsjobtrash.c b/trunk/daemon/gvfsjobtrash.c
new file mode 100644
index 00000000..4869ee3d
--- /dev/null
+++ b/trunk/daemon/gvfsjobtrash.c
@@ -0,0 +1,156 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobtrash.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobTrash, g_vfs_job_trash, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_trash_finalize (GObject *object)
+{
+ GVfsJobTrash *job;
+
+ job = G_VFS_JOB_TRASH (object);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_trash_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_trash_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_trash_class_init (GVfsJobTrashClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_trash_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_trash_init (GVfsJobTrash *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_trash_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobTrash *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_TRASH,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobTrash *op_job = G_VFS_JOB_TRASH (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->trash == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->trash (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobTrash *op_job = G_VFS_JOB_TRASH (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_trash == NULL)
+ return FALSE;
+
+ return class->try_trash (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobtrash.h b/trunk/daemon/gvfsjobtrash.h
new file mode 100644
index 00000000..aa23a03e
--- /dev/null
+++ b/trunk/daemon/gvfsjobtrash.h
@@ -0,0 +1,63 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_TRASH_H__
+#define __G_VFS_JOB_TRASH_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_TRASH (g_vfs_job_trash_get_type ())
+#define G_VFS_JOB_TRASH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_TRASH, GVfsJobTrash))
+#define G_VFS_JOB_TRASH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_TRASH, GVfsJobTrashClass))
+#define G_VFS_IS_JOB_TRASH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_TRASH))
+#define G_VFS_IS_JOB_TRASH_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_TRASH))
+#define G_VFS_JOB_TRASH_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_TRASH, GVfsJobTrashClass))
+
+typedef struct _GVfsJobTrashClass GVfsJobTrashClass;
+
+struct _GVfsJobTrash
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+};
+
+struct _GVfsJobTrashClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_trash_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_trash_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_TRASH_H__ */
diff --git a/trunk/daemon/gvfsjobunmount.c b/trunk/daemon/gvfsjobunmount.c
new file mode 100644
index 00000000..1d7d0a6c
--- /dev/null
+++ b/trunk/daemon/gvfsjobunmount.c
@@ -0,0 +1,169 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobunmount.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobUnmount, g_vfs_job_unmount, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_unmount_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (g_vfs_job_unmount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_unmount_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_unmount_class_init (GVfsJobUnmountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_unmount_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+
+ job_dbus_class->create_reply = create_reply;
+
+}
+
+static void
+g_vfs_job_unmount_init (GVfsJobUnmount *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_unmount_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobUnmount *job;
+
+ g_debug ("g_vfs_job_unmount_new request: %p\n", message);
+
+ job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ class->unmount (op_job->backend,
+ op_job);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_unmount == NULL)
+ {
+ if (class->unmount == NULL)
+ {
+ /* If unmount is not implemented we always succeed */
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ return class->try_unmount (op_job->backend,
+ op_job);
+}
+
+static void
+unregister_mount_callback (DBusMessage *unmount_reply,
+ GError *error,
+ gpointer user_data)
+{
+ GVfsBackend *backend;
+ GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data);
+
+ g_debug ("unregister_mount_callback, unmount_reply: %p, error: %p\n", unmount_reply, error);
+
+ backend = op_job->backend;
+ (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
+
+ /* Unlink job source from daemon */
+ g_vfs_job_source_closed (G_VFS_JOB_SOURCE (backend));
+}
+
+/* Might be called on an i/o thread */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
+
+ g_debug ("send_reply, failed: %d\n", job->failed);
+
+ if (job->failed)
+ (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
+ else
+ g_vfs_backend_unregister_mount (op_job->backend,
+ unregister_mount_callback,
+ job);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobunmount.h b/trunk/daemon/gvfsjobunmount.h
new file mode 100644
index 00000000..aaa18db2
--- /dev/null
+++ b/trunk/daemon/gvfsjobunmount.h
@@ -0,0 +1,62 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_UNMOUNT_H__
+#define __G_VFS_JOB_UNMOUNT_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_UNMOUNT (g_vfs_job_unmount_get_type ())
+#define G_VFS_JOB_UNMOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_UNMOUNT, GVfsJobUnmount))
+#define G_VFS_JOB_UNMOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_UNMOUNT, GVfsJobUnmountClass))
+#define G_VFS_IS_JOB_UNMOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_UNMOUNT))
+#define G_VFS_IS_JOB_UNMOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_UNMOUNT))
+#define G_VFS_JOB_UNMOUNT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_UNMOUNT, GVfsJobUnmountClass))
+
+typedef struct _GVfsJobUnmountClass GVfsJobUnmountClass;
+
+struct _GVfsJobUnmount
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+};
+
+struct _GVfsJobUnmountClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_unmount_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_unmount_new (DBusConnection *connection,
+ DBusMessage *request,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_UNMOUNT_H__ */
diff --git a/trunk/daemon/gvfsjobunmountmountable.c b/trunk/daemon/gvfsjobunmountmountable.c
new file mode 100644
index 00000000..cb9eb22e
--- /dev/null
+++ b/trunk/daemon/gvfsjobunmountmountable.c
@@ -0,0 +1,196 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobunmountmountable.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobUnmountMountable, g_vfs_job_unmount_mountable, G_VFS_TYPE_JOB_DBUS)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_unmount_mountable_finalize (GObject *object)
+{
+ GVfsJobUnmountMountable *job;
+
+ job = G_VFS_JOB_UNMOUNT_MOUNTABLE (object);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_unmount_mountable_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_unmount_mountable_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_unmount_mountable_class_init (GVfsJobUnmountMountableClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_unmount_mountable_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_unmount_mountable_init (GVfsJobUnmountMountable *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_unmount_mountable_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean eject)
+{
+ GVfsJobUnmountMountable *job;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusError derror;
+ char *path;
+ guint32 flags;
+
+ dbus_error_init (&derror);
+ dbus_message_iter_init (message, &iter);
+
+ path = NULL;
+ if (!_g_dbus_message_iter_get_args (&iter, &derror,
+ G_DBUS_TYPE_CSTRING, &path,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ g_free (path);
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = path;
+ job->backend = backend;
+ job->eject = eject;
+ job->flags = flags;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobUnmountMountable *op_job = G_VFS_JOB_UNMOUNT_MOUNTABLE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->eject)
+ {
+ if (class->eject_mountable == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->eject_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else
+ {
+ if (class->unmount_mountable == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->unmount_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobUnmountMountable *op_job = G_VFS_JOB_UNMOUNT_MOUNTABLE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (op_job->eject)
+ {
+ if (class->try_eject_mountable == NULL)
+ return FALSE;
+
+ return class->try_eject_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+ else
+ {
+ if (class->try_unmount_mountable == NULL)
+ return FALSE;
+
+ return class->try_unmount_mountable (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->flags);
+ }
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/trunk/daemon/gvfsjobunmountmountable.h b/trunk/daemon/gvfsjobunmountmountable.h
new file mode 100644
index 00000000..8a1a49d4
--- /dev/null
+++ b/trunk/daemon/gvfsjobunmountmountable.h
@@ -0,0 +1,66 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__
+#define __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__
+
+#include <gio/gio.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE (g_vfs_job_unmount_mountable_get_type ())
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountable))
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountableClass))
+#define G_VFS_IS_JOB_UNMOUNT_MOUNTABLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE))
+#define G_VFS_IS_JOB_UNMOUNT_MOUNTABLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE))
+#define G_VFS_JOB_UNMOUNT_MOUNTABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE, GVfsJobUnmountMountableClass))
+
+typedef struct _GVfsJobUnmountMountableClass GVfsJobUnmountMountableClass;
+
+struct _GVfsJobUnmountMountable
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+ gboolean eject;
+ GMountUnmountFlags flags;
+};
+
+struct _GVfsJobUnmountMountableClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_unmount_mountable_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_unmount_mountable_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend,
+ gboolean eject);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_UNMOUNT_MOUNTABLE_H__ */
diff --git a/trunk/daemon/gvfsjobwrite.c b/trunk/daemon/gvfsjobwrite.c
new file mode 100644
index 00000000..ea3854ff
--- /dev/null
+++ b/trunk/daemon/gvfsjobwrite.c
@@ -0,0 +1,153 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "gvfswritechannel.h"
+#include "gvfsjobwrite.h"
+#include "gvfsdaemonutils.h"
+
+G_DEFINE_TYPE (GVfsJobWrite, g_vfs_job_write, G_VFS_TYPE_JOB)
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static void send_reply (GVfsJob *job);
+
+static void
+g_vfs_job_write_finalize (GObject *object)
+{
+ GVfsJobWrite *job;
+
+ job = G_VFS_JOB_WRITE (object);
+
+ g_object_unref (job->channel);
+ g_free (job->data);
+
+ if (G_OBJECT_CLASS (g_vfs_job_write_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_write_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_write_class_init (GVfsJobWriteClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_write_finalize;
+
+ job_class->run = run;
+ job_class->try = try;
+ job_class->send_reply = send_reply;
+}
+
+static void
+g_vfs_job_write_init (GVfsJobWrite *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ char *data,
+ gsize data_size,
+ GVfsBackend *backend)
+{
+ GVfsJobWrite *job;
+
+ job = g_object_new (G_VFS_TYPE_JOB_WRITE,
+ NULL);
+
+ job->backend = backend;
+ job->channel = g_object_ref (channel);
+ job->handle = handle;
+ /* Takes ownership */
+ job->data = data;
+ job->data_size = data_size;
+ job->written_size = 0;
+
+ return G_VFS_JOB (job);
+}
+
+/* Might be called on an i/o thwrite */
+static void
+send_reply (GVfsJob *job)
+{
+ GVfsJobWrite *op_job = G_VFS_JOB_WRITE (job);
+ g_debug ("job_write send reply\n");
+
+ if (job->failed)
+ g_vfs_channel_send_error (G_VFS_CHANNEL (op_job->channel), job->error);
+ else
+ g_vfs_write_channel_send_written (op_job->channel,
+ op_job->written_size);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobWrite *op_job = G_VFS_JOB_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->write == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->data,
+ op_job->data_size);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobWrite *op_job = G_VFS_JOB_WRITE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_write == NULL)
+ return FALSE;
+
+ return class->try_write (op_job->backend,
+ op_job,
+ op_job->handle,
+ op_job->data,
+ op_job->data_size);
+}
+
+
+void
+g_vfs_job_write_set_written_size (GVfsJobWrite *job,
+ gsize written_size)
+{
+ job->written_size = written_size;
+}
diff --git a/trunk/daemon/gvfsjobwrite.h b/trunk/daemon/gvfsjobwrite.h
new file mode 100644
index 00000000..4974eb2e
--- /dev/null
+++ b/trunk/daemon/gvfsjobwrite.h
@@ -0,0 +1,71 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_JOB_WRITE_H__
+#define __G_VFS_JOB_WRITE_H__
+
+#include <gvfsjob.h>
+#include <gvfsbackend.h>
+#include <gvfswritechannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_WRITE (g_vfs_job_write_get_type ())
+#define G_VFS_JOB_WRITE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_WRITE, GVfsJobWrite))
+#define G_VFS_JOB_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_WRITE, GVfsJobWriteClass))
+#define G_VFS_IS_JOB_WRITE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_WRITE))
+#define G_VFS_IS_JOB_WRITE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_WRITE))
+#define G_VFS_JOB_WRITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_WRITE, GVfsJobWriteClass))
+
+typedef struct _GVfsJobWriteClass GVfsJobWriteClass;
+
+struct _GVfsJobWrite
+{
+ GVfsJob parent_instance;
+
+ GVfsWriteChannel *channel;
+ GVfsBackend *backend;
+ GVfsBackendHandle handle;
+ char *data;
+ gsize data_size;
+
+ gsize written_size;
+};
+
+struct _GVfsJobWriteClass
+{
+ GVfsJobClass parent_class;
+};
+
+GType g_vfs_job_write_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_write_new (GVfsWriteChannel *channel,
+ GVfsBackendHandle handle,
+ char *data,
+ gsize data_size,
+ GVfsBackend *backend);
+void g_vfs_job_write_set_written_size (GVfsJobWrite *job,
+ gsize written_size);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_WRITE_H__ */
diff --git a/trunk/daemon/gvfskeyring.c b/trunk/daemon/gvfskeyring.c
new file mode 100644
index 00000000..943982f8
--- /dev/null
+++ b/trunk/daemon/gvfskeyring.c
@@ -0,0 +1,133 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garcia Campos <carlosgc@gnome.org>
+ */
+
+#include <config.h>
+
+#ifdef HAVE_KEYRING
+#include <gnome-keyring.h>
+#endif
+
+#include "gvfskeyring.h"
+
+gboolean
+g_vfs_keyring_is_available (void)
+{
+#ifdef HAVE_KEYRING
+ return gnome_keyring_is_available ();
+#else
+ return FALSE;
+#endif
+}
+
+gboolean
+g_vfs_keyring_lookup_password (const gchar *username,
+ const gchar *host,
+ const gchar *domain,
+ const gchar *protocol,
+ const gchar *object,
+ const gchar *authtype,
+ guint32 port,
+ gchar **username_out,
+ gchar **domain_out,
+ gchar **password_out)
+{
+#ifdef HAVE_KEYRING
+ GnomeKeyringNetworkPasswordData *pwd_data;
+ GnomeKeyringResult result;
+ GList *plist;
+
+ if (!gnome_keyring_is_available ())
+ return FALSE;
+
+ result = gnome_keyring_find_network_password_sync (
+ username,
+ domain,
+ host,
+ object,
+ protocol,
+ authtype,
+ port,
+ &plist);
+
+ if (result != GNOME_KEYRING_RESULT_OK || plist == NULL)
+ return FALSE;
+
+ /* We use the first result, which is the least specific match */
+ pwd_data = (GnomeKeyringNetworkPasswordData *)plist->data;
+
+ *password_out = g_strdup (pwd_data->password);
+
+ if (username_out)
+ *username_out = g_strdup (pwd_data->user);
+
+ if (domain_out)
+ *domain_out = g_strdup (pwd_data->domain);
+
+ gnome_keyring_network_password_list_free (plist);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif /* HAVE_KEYRING */
+}
+
+gboolean
+g_vfs_keyring_save_password (const gchar *username,
+ const gchar *host,
+ const gchar *domain,
+ const gchar *protocol,
+ const gchar *object,
+ const gchar *authtype,
+ guint32 port,
+ const gchar *password,
+ GPasswordSave flags)
+{
+#ifdef HAVE_KEYRING
+ GnomeKeyringResult result;
+ const gchar *keyring;
+ guint32 item_id;
+
+ if (!gnome_keyring_is_available ())
+ return FALSE;
+
+ if (flags == G_PASSWORD_SAVE_NEVER)
+ return FALSE;
+
+ keyring = (flags == G_PASSWORD_SAVE_FOR_SESSION) ? "session" : NULL;
+
+ result = gnome_keyring_set_network_password_sync (
+ keyring,
+ username,
+ domain,
+ host,
+ object,
+ protocol,
+ authtype,
+ port,
+ password,
+ &item_id);
+
+ return (result == GNOME_KEYRING_RESULT_OK);
+#else
+ return FALSE;
+#endif /* HAVE_KEYRING */
+}
diff --git a/trunk/daemon/gvfskeyring.h b/trunk/daemon/gvfskeyring.h
new file mode 100644
index 00000000..54c04962
--- /dev/null
+++ b/trunk/daemon/gvfskeyring.h
@@ -0,0 +1,53 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Carlos Garcia Campos <carlosgc@gnome.org>
+ */
+
+#ifndef __G_VFS_KEYRING_H__
+#define __G_VFS_KEYRING_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean g_vfs_keyring_is_available (void);
+gboolean g_vfs_keyring_lookup_password (const gchar *username,
+ const gchar *host,
+ const gchar *domain,
+ const gchar *protocol,
+ const gchar *object,
+ const gchar *authtype,
+ guint32 port,
+ gchar **username_out,
+ gchar **domain_out,
+ gchar **password);
+gboolean g_vfs_keyring_save_password (const gchar *username,
+ const gchar *host,
+ const gchar *domain,
+ const gchar *protocol,
+ const gchar *object,
+ const gchar *authtype,
+ guint32 port,
+ const gchar *password,
+ GPasswordSave flags);
+
+G_END_DECLS
+
+#endif /* __G_VFS_KEYRING_H__ */
diff --git a/trunk/daemon/gvfsmonitor.c b/trunk/daemon/gvfsmonitor.c
new file mode 100644
index 00000000..4b91ecef
--- /dev/null
+++ b/trunk/daemon/gvfsmonitor.c
@@ -0,0 +1,323 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gvfsmonitor.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsdaemonutils.h>
+#include <gvfsjobcloseread.h>
+#include <gvfsjobclosewrite.h>
+
+#define OBJ_PATH_PREFIX "/org/gtk/vfs/daemon/dirmonitor/"
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+
+
+/* TODO: Handle a connection dying and unregister its subscription */
+
+typedef struct {
+ DBusConnection *connection;
+ char *id;
+ char *object_path;
+} Subscriber;
+
+struct _GVfsMonitorPrivate
+{
+ GVfsDaemon *daemon;
+ GVfsBackend *backend; /* weak ref */
+ GMountSpec *mount_spec;
+ char *object_path;
+ GList *subscribers;
+};
+
+/* atomic */
+static volatile gint path_counter = 1;
+
+G_DEFINE_TYPE (GVfsMonitor, g_vfs_monitor, G_TYPE_OBJECT)
+
+static void unsubscribe (GVfsMonitor *monitor,
+ Subscriber *subscriber);
+
+static void
+backend_died (GVfsMonitor *monitor,
+ GObject *old_backend)
+{
+ Subscriber *subscriber;
+
+ monitor->priv->backend = NULL;
+
+ while (monitor->priv->subscribers != NULL)
+ {
+ subscriber = monitor->priv->subscribers->data;
+ unsubscribe (monitor, subscriber);
+ }
+}
+
+static void
+g_vfs_monitor_finalize (GObject *object)
+{
+ GVfsMonitor *monitor;
+
+ monitor = G_VFS_MONITOR (object);
+
+ if (monitor->priv->backend)
+ g_object_weak_unref (G_OBJECT (monitor->priv->backend),
+ (GWeakNotify)backend_died,
+ monitor);
+
+ g_vfs_daemon_unregister_path (monitor->priv->daemon, monitor->priv->object_path);
+ g_object_unref (monitor->priv->daemon);
+
+ g_mount_spec_unref (monitor->priv->mount_spec);
+
+ g_free (monitor->priv->object_path);
+
+ if (G_OBJECT_CLASS (g_vfs_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_monitor_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_monitor_class_init (GVfsMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GVfsMonitorPrivate));
+
+ gobject_class->finalize = g_vfs_monitor_finalize;
+}
+
+static void
+g_vfs_monitor_init (GVfsMonitor *monitor)
+{
+ gint id;
+
+ monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
+ G_TYPE_VFS_MONITOR,
+ GVfsMonitorPrivate);
+
+ id = g_atomic_int_exchange_and_add (&path_counter, 1);
+ monitor->priv->object_path = g_strdup_printf (OBJ_PATH_PREFIX"%d", id);
+}
+
+static gboolean
+matches_subscriber (Subscriber *subscriber,
+ DBusConnection *connection,
+ const char *object_path,
+ const char *dbus_id)
+{
+ return (subscriber->connection == connection &&
+ strcmp (subscriber->object_path, object_path) == 0 &&
+ ((dbus_id == NULL && subscriber->id == NULL) ||
+ (dbus_id != NULL && subscriber->id != NULL &&
+ strcmp (subscriber->id, dbus_id) == 0)));
+}
+
+static void
+unsubscribe (GVfsMonitor *monitor,
+ Subscriber *subscriber)
+{
+ monitor->priv->subscribers = g_list_remove (monitor->priv->subscribers, subscriber);
+
+ dbus_connection_unref (subscriber->connection);
+ g_free (subscriber->id);
+ g_free (subscriber->object_path);
+ g_free (subscriber);
+ g_object_unref (monitor);
+}
+
+static DBusHandlerResult
+vfs_monitor_message_callback (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GVfsMonitor *monitor = user_data;
+ char *object_path;
+ DBusError derror;
+ GList *l;
+ Subscriber *subscriber;
+ DBusMessage *reply;
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MONITOR_INTERFACE,
+ G_VFS_DBUS_MONITOR_OP_SUBSCRIBE))
+ {
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_OBJECT_PATH, &object_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ }
+ else
+ {
+ subscriber = g_new0 (Subscriber, 1);
+ subscriber->connection = dbus_connection_ref (connection);
+ subscriber->id = g_strdup (dbus_message_get_sender (message));
+ subscriber->object_path = g_strdup (object_path);
+
+ g_object_ref (monitor);
+ monitor->priv->subscribers = g_list_prepend (monitor->priv->subscribers, subscriber);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MONITOR_INTERFACE,
+ G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE))
+ {
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_OBJECT_PATH, &object_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ }
+ else
+ {
+ g_object_ref (monitor); /* Keep alive during possible last remove */
+ for (l = monitor->priv->subscribers; l != NULL; l = l->next)
+ {
+ subscriber = l->data;
+
+ if (matches_subscriber (subscriber,
+ connection,
+ object_path,
+ dbus_message_get_sender (message)))
+ {
+ unsubscribe (monitor, subscriber);
+ break;
+ }
+ }
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+
+ g_object_unref (monitor);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+}
+
+GVfsMonitor *
+g_vfs_monitor_new (GVfsBackend *backend)
+{
+ GVfsMonitor *monitor;
+
+ monitor = g_object_new (G_TYPE_VFS_MONITOR, NULL);
+
+ monitor->priv->backend = backend;
+
+ g_object_weak_ref (G_OBJECT (backend),
+ (GWeakNotify)backend_died,
+ monitor);
+
+ monitor->priv->daemon = g_object_ref (g_vfs_backend_get_daemon (backend));
+ monitor->priv->mount_spec = g_mount_spec_ref (g_vfs_backend_get_mount_spec (backend));
+
+ g_vfs_daemon_register_path (monitor->priv->daemon,
+ monitor->priv->object_path,
+ vfs_monitor_message_callback,
+ monitor);
+
+ return monitor;
+}
+
+const char *
+g_vfs_monitor_get_object_path (GVfsMonitor *monitor)
+{
+ return monitor->priv->object_path;
+}
+
+void
+g_vfs_monitor_emit_event (GVfsMonitor *monitor,
+ GFileMonitorEvent event_type,
+ const char *file_path,
+ const char *other_file_path)
+{
+ GList *l;
+ Subscriber *subscriber;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ guint32 event_type_dbus;
+
+ for (l = monitor->priv->subscribers; l != NULL; l = l->next)
+ {
+ subscriber = l->data;
+
+ message =
+ dbus_message_new_method_call (subscriber->id,
+ subscriber->object_path,
+ G_VFS_DBUS_MONITOR_CLIENT_INTERFACE,
+ G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED);
+
+ dbus_message_iter_init_append (message, &iter);
+ event_type_dbus = event_type;
+ dbus_message_iter_append_basic (&iter,
+ DBUS_TYPE_UINT32,
+ &event_type_dbus);
+ g_mount_spec_to_dbus (&iter, monitor->priv->mount_spec);
+ _g_dbus_message_iter_append_cstring (&iter, file_path);
+
+ if (other_file_path)
+ {
+ g_mount_spec_to_dbus (&iter, monitor->priv->mount_spec);
+ _g_dbus_message_iter_append_cstring (&iter, other_file_path);
+ }
+
+ dbus_message_set_no_reply (message, FALSE);
+
+ dbus_connection_send (subscriber->connection, message, NULL);
+ dbus_message_unref (message);
+ }
+}
diff --git a/trunk/daemon/gvfsmonitor.h b/trunk/daemon/gvfsmonitor.h
new file mode 100644
index 00000000..65ec82ff
--- /dev/null
+++ b/trunk/daemon/gvfsmonitor.h
@@ -0,0 +1,67 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_MONITOR_H__
+#define __G_VFS_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_VFS_MONITOR (g_vfs_monitor_get_type ())
+#define G_VFS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_VFS_MONITOR, GVfsMonitor))
+#define G_VFS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_VFS_MONITOR, GVfsMonitorClass))
+#define G_IS_VFS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_VFS_MONITOR))
+#define G_IS_VFS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_VFS_MONITOR))
+
+typedef struct _GVfsMonitor GVfsMonitor;
+typedef struct _GVfsMonitorClass GVfsMonitorClass;
+typedef struct _GVfsMonitorPrivate GVfsMonitorPrivate;
+
+struct _GVfsMonitor
+{
+ GObject parent_instance;
+
+ GVfsMonitorPrivate *priv;
+};
+
+
+struct _GVfsMonitorClass
+{
+ GObjectClass parent_class;
+
+};
+
+GType g_vfs_monitor_get_type (void) G_GNUC_CONST;
+
+GVfsMonitor* g_vfs_monitor_new (GVfsBackend *backend);
+const char * g_vfs_monitor_get_object_path (GVfsMonitor *monitor);
+void g_vfs_monitor_emit_event (GVfsMonitor *monitor,
+ GFileMonitorEvent event_type,
+ const char *file_path,
+ const char *other_file_path);
+
+G_END_DECLS
+
+#endif /* __G_VFS_MONITOR_H__ */
diff --git a/trunk/daemon/gvfsreadchannel.c b/trunk/daemon/gvfsreadchannel.c
new file mode 100644
index 00000000..1f043b85
--- /dev/null
+++ b/trunk/daemon/gvfsreadchannel.c
@@ -0,0 +1,290 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gvfsreadchannel.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsdaemonutils.h>
+#include <gvfsjobread.h>
+#include <gvfsjobseekread.h>
+#include <gvfsjobqueryinforead.h>
+#include <gvfsjobcloseread.h>
+#include <gvfsfileinfo.h>
+
+struct _GVfsReadChannel
+{
+ GVfsChannel parent_instance;
+
+ guint read_count;
+ int seek_generation;
+};
+
+G_DEFINE_TYPE (GVfsReadChannel, g_vfs_read_channel, G_VFS_TYPE_CHANNEL)
+
+static GVfsJob *read_channel_close (GVfsChannel *channel);
+static GVfsJob *read_channel_handle_request (GVfsChannel *channel,
+ guint32 command,
+ guint32 seq_nr,
+ guint32 arg1,
+ guint32 arg2,
+ gpointer data,
+ gsize data_len,
+ GError **error);
+static GVfsJob *read_channel_readahead (GVfsChannel *channel,
+ GVfsJob *job);
+
+static void
+g_vfs_read_channel_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (g_vfs_read_channel_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_read_channel_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_read_channel_class_init (GVfsReadChannelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsChannelClass *channel_class = G_VFS_CHANNEL_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_read_channel_finalize;
+ channel_class->close = read_channel_close;
+ channel_class->handle_request = read_channel_handle_request;
+ channel_class->readahead = read_channel_readahead;
+}
+
+static void
+g_vfs_read_channel_init (GVfsReadChannel *channel)
+{
+}
+
+static GVfsJob *
+read_channel_close (GVfsChannel *channel)
+{
+ return g_vfs_job_close_read_new (G_VFS_READ_CHANNEL (channel),
+ g_vfs_channel_get_backend_handle (channel),
+ g_vfs_channel_get_backend (channel));
+}
+
+/* Always request large chunks. Its very inefficient
+ to do network requests for smaller chunks. */
+static guint32
+modify_read_size (GVfsReadChannel *channel,
+ guint32 requested_size)
+{
+ guint32 real_size;
+
+ if (channel->read_count <= 1)
+ real_size = 16*1024;
+ else if (channel->read_count <= 2)
+ real_size = 32*1024;
+ else
+ real_size = 64*1024;
+
+ if (requested_size > real_size)
+ real_size = requested_size;
+
+ /* Don't do ridicoulously large requests as this
+ is just stupid on the network */
+ if (real_size > 512 * 1024)
+ real_size = 512 * 1024;
+
+ return real_size;
+}
+
+static GVfsJob *
+read_channel_handle_request (GVfsChannel *channel,
+ guint32 command,
+ guint32 seq_nr,
+ guint32 arg1,
+ guint32 arg2,
+ gpointer data,
+ gsize data_len,
+ GError **error)
+{
+ GVfsJob *job;
+ GSeekType seek_type;
+ GVfsBackendHandle backend_handle;
+ GVfsBackend *backend;
+ GVfsReadChannel *read_channel;
+ char *attrs;
+
+ read_channel = G_VFS_READ_CHANNEL (channel);
+ backend_handle = g_vfs_channel_get_backend_handle (channel);
+ backend = g_vfs_channel_get_backend (channel);
+
+ job = NULL;
+ switch (command)
+ {
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ:
+ read_channel->read_count++;
+ job = g_vfs_job_read_new (read_channel,
+ backend_handle,
+ modify_read_size (read_channel, arg1),
+ backend);
+ break;
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE:
+ job = g_vfs_job_close_read_new (read_channel,
+ backend_handle,
+ backend);
+ break;
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END:
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET:
+ seek_type = G_SEEK_SET;
+ if (command == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END)
+ seek_type = G_SEEK_END;
+
+ read_channel->read_count = 0;
+ read_channel->seek_generation++;
+ job = g_vfs_job_seek_read_new (read_channel,
+ backend_handle,
+ seek_type,
+ ((goffset)arg1) | (((goffset)arg2) << 32),
+ backend);
+ break;
+
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_QUERY_INFO:
+ attrs = g_strndup (data, data_len);
+ job = g_vfs_job_query_info_read_new (read_channel,
+ backend_handle,
+ attrs,
+ backend);
+
+ g_free (attrs);
+ break;
+
+ default:
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unknown stream command %"G_GUINT32_FORMAT, command);
+ break;
+ }
+
+ /* Ownership was passed */
+ g_free (data);
+ return job;
+}
+
+static GVfsJob *
+read_channel_readahead (GVfsChannel *channel,
+ GVfsJob *job)
+{
+ GVfsJob *readahead_job;
+ GVfsReadChannel *read_channel;
+ GVfsJobRead *read_job;
+
+ readahead_job = NULL;
+ if (!job->failed &&
+ G_VFS_IS_JOB_READ (job))
+ {
+ read_job = G_VFS_JOB_READ (job);
+ read_channel = G_VFS_READ_CHANNEL (channel);
+
+ if (read_job->data_count != 0)
+ {
+ read_channel->read_count++;
+ readahead_job = g_vfs_job_read_new (read_channel,
+ g_vfs_channel_get_backend_handle (channel),
+ modify_read_size (read_channel, 8192),
+ g_vfs_channel_get_backend (channel));
+ }
+ }
+
+ return readahead_job;
+}
+
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_read_channel_send_seek_offset (GVfsReadChannel *read_channel,
+ goffset offset)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (read_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (offset & 0xffffffff);
+ reply.arg2 = g_htonl (offset >> 32);
+
+ g_vfs_channel_send_reply (channel, &reply, NULL, 0);
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_read_channel_send_closed (GVfsReadChannel *read_channel)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (read_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (0);
+ reply.arg2 = g_htonl (0);
+
+ g_vfs_channel_send_reply (channel, &reply, NULL, 0);
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_read_channel_send_data (GVfsReadChannel *read_channel,
+ char *buffer,
+ gsize count)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (read_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (count);
+ reply.arg2 = g_htonl (read_channel->seek_generation);
+
+ g_vfs_channel_send_reply (channel, &reply, buffer, count);
+}
+
+
+GVfsReadChannel *
+g_vfs_read_channel_new (GVfsBackend *backend)
+{
+ return g_object_new (G_VFS_TYPE_READ_CHANNEL,
+ "backend", backend,
+ NULL);
+}
diff --git a/trunk/daemon/gvfsreadchannel.h b/trunk/daemon/gvfsreadchannel.h
new file mode 100644
index 00000000..a9a18bbf
--- /dev/null
+++ b/trunk/daemon/gvfsreadchannel.h
@@ -0,0 +1,60 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_READ_CHANNEL_H__
+#define __G_VFS_READ_CHANNEL_H__
+
+#include <glib-object.h>
+#include <gvfsjob.h>
+#include <gvfschannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_READ_CHANNEL (g_vfs_read_channel_get_type ())
+#define G_VFS_READ_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_READ_CHANNEL, GVfsReadChannel))
+#define G_VFS_READ_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_READ_CHANNEL, GVfsReadChannelClass))
+#define G_VFS_IS_READ_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_READ_CHANNEL))
+#define G_VFS_IS_READ_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_READ_CHANNEL))
+#define G_VFS_READ_CHANNEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_READ_CHANNEL, GVfsReadChannelClass))
+
+typedef struct _GVfsReadChannel GVfsReadChannel;
+typedef struct _GVfsReadChannelClass GVfsReadChannelClass;
+typedef struct _GVfsReadChannelPrivate GVfsReadChannelPrivate;
+
+struct _GVfsReadChannelClass
+{
+ GVfsChannelClass parent_class;
+};
+
+GType g_vfs_read_channel_get_type (void) G_GNUC_CONST;
+
+GVfsReadChannel *g_vfs_read_channel_new (GVfsBackend *backend);
+void g_vfs_read_channel_send_data (GVfsReadChannel *read_channel,
+ char *buffer,
+ gsize count);
+void g_vfs_read_channel_send_closed (GVfsReadChannel *read_channel);
+void g_vfs_read_channel_send_seek_offset (GVfsReadChannel *read_channel,
+ goffset offset);
+
+G_END_DECLS
+
+#endif /* __G_VFS_READ_CHANNEL_H__ */
diff --git a/trunk/daemon/gvfswritechannel.c b/trunk/daemon/gvfswritechannel.c
new file mode 100644
index 00000000..1646aceb
--- /dev/null
+++ b/trunk/daemon/gvfswritechannel.c
@@ -0,0 +1,226 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gvfswritechannel.h>
+#include <gvfsdaemonprotocol.h>
+#include <gvfsdaemonutils.h>
+#include <gvfsjobwrite.h>
+#include <gvfsjobseekwrite.h>
+#include <gvfsjobclosewrite.h>
+#include <gvfsjobqueryinfowrite.h>
+
+struct _GVfsWriteChannel
+{
+ GVfsChannel parent_instance;
+};
+
+G_DEFINE_TYPE (GVfsWriteChannel, g_vfs_write_channel, G_VFS_TYPE_CHANNEL)
+
+static GVfsJob *write_channel_close (GVfsChannel *channel);
+static GVfsJob *write_channel_handle_request (GVfsChannel *channel,
+ guint32 command,
+ guint32 seq_nr,
+ guint32 arg1,
+ guint32 arg2,
+ gpointer data,
+ gsize data_len,
+ GError **error);
+
+static void
+g_vfs_write_channel_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (g_vfs_write_channel_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_write_channel_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_write_channel_class_init (GVfsWriteChannelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsChannelClass *channel_class = G_VFS_CHANNEL_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_write_channel_finalize;
+ channel_class->close = write_channel_close;
+ channel_class->handle_request = write_channel_handle_request;
+}
+
+static void
+g_vfs_write_channel_init (GVfsWriteChannel *channel)
+{
+}
+
+static GVfsJob *
+write_channel_close (GVfsChannel *channel)
+{
+ return g_vfs_job_close_write_new (G_VFS_WRITE_CHANNEL (channel),
+ g_vfs_channel_get_backend_handle (channel),
+ g_vfs_channel_get_backend (channel));
+}
+
+static GVfsJob *
+write_channel_handle_request (GVfsChannel *channel,
+ guint32 command,
+ guint32 seq_nr,
+ guint32 arg1,
+ guint32 arg2,
+ gpointer data,
+ gsize data_len,
+ GError **error)
+{
+ GVfsJob *job;
+ GSeekType seek_type;
+ GVfsBackendHandle backend_handle;
+ GVfsBackend *backend;
+ GVfsWriteChannel *write_channel;
+ char *attrs;
+
+ write_channel = G_VFS_WRITE_CHANNEL (channel);
+ backend_handle = g_vfs_channel_get_backend_handle (channel);
+ backend = g_vfs_channel_get_backend (channel);
+
+ job = NULL;
+ switch (command)
+ {
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE:
+ job = g_vfs_job_write_new (write_channel,
+ backend_handle,
+ data, data_len,
+ backend);
+ data = NULL; /* Pass ownership */
+ break;
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE:
+ job = g_vfs_job_close_write_new (write_channel,
+ backend_handle,
+ backend);
+ break;
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END:
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET:
+ seek_type = G_SEEK_SET;
+ if (command == G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END)
+ seek_type = G_SEEK_END;
+
+ job = g_vfs_job_seek_write_new (write_channel,
+ backend_handle,
+ seek_type,
+ ((goffset)arg1) | (((goffset)arg2) << 32),
+ backend);
+ break;
+
+ case G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_QUERY_INFO:
+ attrs = g_strndup (data, data_len);
+ job = g_vfs_job_query_info_write_new (write_channel,
+ backend_handle,
+ attrs,
+ backend);
+ g_free (attrs);
+ break;
+
+ default:
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Unknown stream command %"G_GUINT32_FORMAT, command);
+ break;
+ }
+
+ /* Ownership was passed */
+ g_free (data);
+ return job;
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_write_channel_send_seek_offset (GVfsWriteChannel *write_channel,
+ goffset offset)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (write_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (offset & 0xffffffff);
+ reply.arg2 = g_htonl (offset >> 32);
+
+ g_vfs_channel_send_reply (channel, &reply, NULL, 0);
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_write_channel_send_closed (GVfsWriteChannel *write_channel,
+ const char *etag)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (write_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (0);
+ reply.arg2 = g_htonl (strlen (etag));
+
+ g_vfs_channel_send_reply (channel, &reply, etag, strlen (etag));
+}
+
+/* Might be called on an i/o thread
+ */
+void
+g_vfs_write_channel_send_written (GVfsWriteChannel *write_channel,
+ gsize bytes_written)
+{
+ GVfsDaemonSocketProtocolReply reply;
+ GVfsChannel *channel;
+
+ channel = G_VFS_CHANNEL (write_channel);
+
+ reply.type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN);
+ reply.seq_nr = g_htonl (g_vfs_channel_get_current_seq_nr (channel));
+ reply.arg1 = g_htonl (bytes_written);
+ reply.arg2 = 0;
+
+ g_vfs_channel_send_reply (channel, &reply, NULL, 0);
+}
+
+
+GVfsWriteChannel *
+g_vfs_write_channel_new (GVfsBackend *backend)
+{
+ return g_object_new (G_VFS_TYPE_WRITE_CHANNEL,
+ "backend", backend,
+ NULL);
+}
diff --git a/trunk/daemon/gvfswritechannel.h b/trunk/daemon/gvfswritechannel.h
new file mode 100644
index 00000000..ce4dc14e
--- /dev/null
+++ b/trunk/daemon/gvfswritechannel.h
@@ -0,0 +1,60 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_VFS_WRITE_CHANNEL_H__
+#define __G_VFS_WRITE_CHANNEL_H__
+
+#include <glib-object.h>
+#include <gvfsjob.h>
+#include <gvfschannel.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_WRITE_CHANNEL (g_vfs_write_channel_get_type ())
+#define G_VFS_WRITE_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_WRITE_CHANNEL, GVfsWriteChannel))
+#define G_VFS_WRITE_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_WRITE_CHANNEL, GVfsWriteChannelClass))
+#define G_VFS_IS_WRITE_CHANNEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_WRITE_CHANNEL))
+#define G_VFS_IS_WRITE_CHANNEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_WRITE_CHANNEL))
+#define G_VFS_WRITE_CHANNEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_WRITE_CHANNEL, GVfsWriteChannelClass))
+
+typedef struct _GVfsWriteChannel GVfsWriteChannel;
+typedef struct _GVfsWriteChannelClass GVfsWriteChannelClass;
+typedef struct _GVfsWriteChannelPrivate GVfsWriteChannelPrivate;
+
+struct _GVfsWriteChannelClass
+{
+ GVfsChannelClass parent_class;
+};
+
+GType g_vfs_write_channel_get_type (void) G_GNUC_CONST;
+
+GVfsWriteChannel *g_vfs_write_channel_new (GVfsBackend *backend);
+void g_vfs_write_channel_send_written (GVfsWriteChannel *write_channel,
+ gsize bytes_written);
+void g_vfs_write_channel_send_closed (GVfsWriteChannel *write_channel,
+ const char *etag);
+void g_vfs_write_channel_send_seek_offset (GVfsWriteChannel *write_channel,
+ goffset offset);
+
+G_END_DECLS
+
+#endif /* __G_VFS_WRITE_CHANNEL_H__ */
diff --git a/trunk/daemon/http.mount.in b/trunk/daemon/http.mount.in
new file mode 100644
index 00000000..21b7930b
--- /dev/null
+++ b/trunk/daemon/http.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=http
+Exec=@libexecdir@/gvfsd-http
+AutoMount=true
+DBusName=org.gtk.vfs.mountpoint.http
diff --git a/trunk/daemon/libsmb-compat.h b/trunk/daemon/libsmb-compat.h
new file mode 100644
index 00000000..6ce468c9
--- /dev/null
+++ b/trunk/daemon/libsmb-compat.h
@@ -0,0 +1,200 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * libsmb-compat.h: compatibility macros for libsmbclient < 3.2.0-pre2
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Tomas Bzatek <tbzatek@redhat.com>
+ */
+
+#include <config.h>
+
+#include <libsmbclient.h>
+
+
+
+#ifndef DEPRECATED_SMBC_INTERFACE
+
+
+typedef SMBCFILE * (*smbc_opendir_fn)(SMBCCTX *c,
+ const char *fname);
+
+typedef int (*smbc_closedir_fn)(SMBCCTX *c,
+ SMBCFILE *dir);
+
+typedef struct smbc_dirent * (*smbc_readdir_fn)(SMBCCTX *c,
+ SMBCFILE *dir);
+
+typedef int (*smbc_getdents_fn)(SMBCCTX *c,
+ SMBCFILE *dir,
+ struct smbc_dirent *dirp,
+ int count);
+
+typedef int (*smbc_stat_fn)(SMBCCTX *c,
+ const char *fname,
+ struct stat *st);
+
+typedef SMBCFILE * (*smbc_open_fn)(SMBCCTX *c,
+ const char *fname,
+ int flags,
+ mode_t mode);
+
+typedef SMBCFILE * (*smbc_creat_fn)(SMBCCTX *c,
+ const char *path,
+ mode_t mode);
+
+typedef ssize_t (*smbc_read_fn)(SMBCCTX *c,
+ SMBCFILE *file,
+ void *buf,
+ size_t count);
+
+typedef ssize_t (*smbc_write_fn)(SMBCCTX *c,
+ SMBCFILE *file,
+ void *buf,
+ size_t count);
+
+typedef int (*smbc_unlink_fn)(SMBCCTX *c,
+ const char *fname);
+
+typedef int (*smbc_rename_fn)(SMBCCTX *ocontext,
+ const char *oname,
+ SMBCCTX *ncontext,
+ const char *nname);
+
+typedef off_t (*smbc_lseek_fn)(SMBCCTX *c,
+ SMBCFILE * file,
+ off_t offset,
+ int whence);
+
+typedef int (*smbc_close_fn)(SMBCCTX *c,
+ SMBCFILE *file);
+
+typedef int (*smbc_fstat_fn)(SMBCCTX *c,
+ SMBCFILE *file,
+ struct stat *st);
+
+typedef int (*smbc_rmdir_fn)(SMBCCTX *c,
+ const char *fname);
+
+typedef int (*smbc_mkdir_fn)(SMBCCTX *c,
+ const char *fname,
+ mode_t mode);
+
+typedef int (*smbc_chmod_fn)(SMBCCTX *c,
+ const char *fname,
+ mode_t mode);
+
+typedef int (*smbc_utimes_fn)(SMBCCTX *c,
+ const char *fname,
+ struct timeval *tbuf);
+
+
+
+#define smbc_getOptionUserData(ctx) \
+ smbc_option_get (ctx, "user_data")
+
+#define smbc_setOptionUserData(ctx, data) \
+ smbc_option_set (ctx, "user_data", data)
+
+#define smbc_setDebug(ctx, d) \
+ ctx->debug = d
+
+#define smbc_setFunctionAuthDataWithContext(ctx, func) { \
+ ctx->callbacks.auth_fn = NULL; \
+ smbc_option_set (ctx, "auth_function", \
+ (void *) func); \
+ }
+
+#define smbc_setFunctionAddCachedServer(ctx, func) \
+ ctx->callbacks.add_cached_srv_fn = func
+
+#define smbc_setFunctionGetCachedServer(ctx, func) \
+ ctx->callbacks.get_cached_srv_fn = func
+
+#define smbc_setFunctionRemoveCachedServer(ctx, func) \
+ ctx->callbacks.remove_cached_srv_fn = func
+
+#define smbc_setFunctionPurgeCachedServers(ctx, func) \
+ ctx->callbacks.purge_cached_fn = func
+
+/* libsmbclient frees this on it's own, so make sure
+ * to use simple system malloc */
+#define smbc_setWorkgroup(ctx, data) \
+ ctx->workgroup = strdup (data)
+
+#define smbc_getWorkgroup(ctx) \
+ ctx->workgroup
+
+#if defined(HAVE_SAMBA_FLAGS) && defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
+ #define smbc_setOptionUseKerberos(ctx, val) \
+ ctx->flags |= SMB_CTX_FLAG_USE_KERBEROS
+#else
+ #define smbc_setOptionUseKerberos(ctx, val) { }
+#endif
+
+#if defined(HAVE_SAMBA_FLAGS) && defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
+ #define smbc_setOptionFallbackAfterKerberos(ctx, val) \
+ ctx->flags |= SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS
+#else
+ #define smbc_setOptionFallbackAfterKerberos(ctx, val) { }
+#endif
+
+#if defined(HAVE_SAMBA_FLAGS) && defined(SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON)
+ #define smbc_setOptionNoAutoAnonymousLogin(ctx, val) \
+ ctx->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON
+#else
+ #define smbc_setOptionNoAutoAnonymousLogin(ctx, val) { }
+#endif
+
+
+#define smbc_setOptionDebugToStderr(ctx, val) \
+ smbc_option_set(ctx, "debug_stderr", (void *) val)
+
+#define smbc_getFunctionStat(ctx) ctx->stat
+
+#define smbc_getFunctionFstat(ctx) ctx->fstat
+
+#define smbc_getFunctionOpen(ctx) ctx->open
+
+#define smbc_getFunctionRead(ctx) ctx->read
+
+#define smbc_getFunctionWrite(ctx) ctx->write
+
+#define smbc_getFunctionLseek(ctx) ctx->lseek
+
+#define smbc_getFunctionClose(ctx) ctx->close_fn
+
+#define smbc_getFunctionUnlink(ctx) ctx->unlink
+
+#define smbc_getFunctionRename(ctx) ctx->rename
+
+#define smbc_getFunctionOpendir(ctx) ctx->opendir
+
+#define smbc_getFunctionGetdents(ctx) ctx->getdents
+
+#define smbc_getFunctionClosedir(ctx) ctx->closedir
+
+#define smbc_getFunctionRmdir(ctx) ctx->rmdir
+
+#define smbc_getFunctionMkdir(ctx) ctx->mkdir
+
+#define smbc_getFunctionChmod(ctx) ctx->chmod
+
+#define smbc_getFunctionUtimes(ctx) ctx->utimes
+
+
+#endif
diff --git a/trunk/daemon/localtest.mount.in b/trunk/daemon/localtest.mount.in
new file mode 100644
index 00000000..b3cbea74
--- /dev/null
+++ b/trunk/daemon/localtest.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=localtest
+Exec=@libexecdir@/gvfsd-localtest
+AutoMount=false
diff --git a/trunk/daemon/main.c b/trunk/daemon/main.c
new file mode 100644
index 00000000..757229d2
--- /dev/null
+++ b/trunk/daemon/main.c
@@ -0,0 +1,131 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <dbus/dbus.h>
+#include "gvfsdaemon.h"
+#include "gvfsbackendtest.h"
+#include <gvfsdaemonprotocol.h>
+#include "mount.h"
+#include <locale.h>
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *loop;
+ GVfsDaemon *daemon;
+ gboolean replace;
+ gboolean no_fuse;
+ GError *error;
+ GOptionContext *context;
+ const GOptionEntry options[] = {
+ { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, N_("Replace old daemon."), NULL },
+ { "no-fuse", 0, 0, G_OPTION_ARG_NONE, &no_fuse, N_("Don't start fuse."), NULL },
+ { NULL }
+ };
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ g_thread_init (NULL);
+
+ g_set_application_name (_("GVFS Daemon"));
+ context = g_option_context_new ("");
+
+ g_option_context_set_summary (context, _("Main daemon for GVFS"));
+
+ g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
+
+ replace = FALSE;
+ no_fuse = FALSE;
+
+ if (g_getenv ("GVFS_DISABLE_FUSE") != NULL)
+ no_fuse = TRUE;
+
+ error = NULL;
+ if (!g_option_context_parse (context, &argc, &argv, &error))
+ {
+ /* Translators: the first %s is the application name, */
+ /* the second %s is the error message */
+ g_printerr (_("%s: %s"), g_get_application_name(), error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free (error);
+ g_option_context_free (context);
+ return 1;
+ }
+
+ g_option_context_free (context);
+
+ dbus_threads_init_default ();
+
+ g_type_init ();
+
+ daemon = g_vfs_daemon_new (TRUE, replace);
+ if (daemon == NULL)
+ return 1;
+
+ mount_init ();
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+
+#ifdef HAVE_FUSE
+ if (!no_fuse)
+ {
+ char *fuse_path;
+ char *argv2[3];
+
+ fuse_path = g_build_filename (g_get_home_dir (), ".gvfs", NULL);
+
+ if (!g_file_test (fuse_path, G_FILE_TEST_EXISTS))
+ g_mkdir (fuse_path, 0700);
+
+ argv2[0] = LIBEXEC_DIR "/gvfs-fuse-daemon";
+ argv2[1] = fuse_path;
+ argv2[2] = NULL;
+
+ g_spawn_async (NULL,
+ argv2,
+ NULL,
+ G_SPAWN_STDOUT_TO_DEV_NULL |
+ G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL,
+ NULL, NULL);
+
+ g_free (fuse_path);
+ }
+#endif
+
+ g_main_loop_run (loop);
+
+ return 0;
+}
diff --git a/trunk/daemon/mount.c b/trunk/daemon/mount.c
new file mode 100644
index 00000000..172728f1
--- /dev/null
+++ b/trunk/daemon/mount.c
@@ -0,0 +1,1280 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "mount.h"
+#include "gmountoperationdbus.h"
+#include "gvfsdaemonprotocol.h"
+#include "gdbusutils.h"
+#include <glib.h>
+#include <gio/gio.h>
+
+typedef struct {
+ char *display_name;
+ char *stable_name;
+ char *x_content_types;
+ char *icon;
+ char *prefered_filename_encoding;
+ gboolean user_visible;
+ char *fuse_mountpoint; /* Always set, even if fuse not availible */
+
+ /* Daemon object ref */
+ char *dbus_id;
+ char *object_path;
+
+ /* Mount details */
+ GMountSpec *mount_spec;
+} VfsMount;
+
+typedef struct {
+ char *type;
+ char *exec;
+ char *dbus_name;
+ gboolean automount;
+ char *scheme;
+ char **scheme_aliases;
+ int default_port;
+ gboolean hostname_is_inet;
+} VfsMountable;
+
+typedef void (*MountCallback) (VfsMountable *mountable,
+ GError *error,
+ gpointer user_data);
+
+static GList *mountables = NULL;
+static GList *mounts = NULL;
+
+static gboolean fuse_available;
+
+static void lookup_mount (DBusConnection *connection,
+ DBusMessage *message,
+ gboolean do_automount);
+static void mountable_mount (VfsMountable *mountable,
+ GMountSpec *mount_spec,
+ GMountSource *source,
+ gboolean automount,
+ MountCallback callback,
+ gpointer user_data);
+
+static VfsMount *
+find_vfs_mount (const char *dbus_id,
+ const char *obj_path)
+{
+ GList *l;
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ VfsMount *mount = l->data;
+
+ if (strcmp (mount->dbus_id, dbus_id) == 0 &&
+ strcmp (mount->object_path, obj_path) == 0)
+ return mount;
+ }
+
+ return NULL;
+}
+
+static VfsMount *
+find_vfs_mount_by_fuse_path (const char *fuse_path)
+{
+ GList *l;
+
+ if (!fuse_available)
+ return NULL;
+
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ VfsMount *mount = l->data;
+
+ if (mount->fuse_mountpoint != NULL &&
+ g_str_has_prefix (fuse_path, mount->fuse_mountpoint))
+ {
+ int len = strlen (mount->fuse_mountpoint);
+ if (fuse_path[len] == 0 ||
+ fuse_path[len] == '/')
+ return mount;
+ }
+ }
+
+ return NULL;
+}
+
+
+static VfsMount *
+match_vfs_mount (GMountSpec *match)
+{
+ GList *l;
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ VfsMount *mount = l->data;
+
+ if (g_mount_spec_match (mount->mount_spec, match))
+ return mount;
+ }
+
+ return NULL;
+}
+
+static VfsMountable *
+find_mountable (const char *type)
+{
+ GList *l;
+
+ for (l = mountables; l != NULL; l = l->next)
+ {
+ VfsMountable *mountable = l->data;
+
+ if (strcmp (mountable->type, type) == 0)
+ return mountable;
+ }
+
+ return NULL;
+}
+
+static VfsMountable *
+lookup_mountable (GMountSpec *spec)
+{
+ const char *type;
+
+ type = g_mount_spec_get_type (spec);
+ if (type == NULL)
+ return NULL;
+
+ return find_mountable (type);
+}
+
+static void
+vfs_mountable_free (VfsMountable *mountable)
+{
+ g_free (mountable->type);
+ g_free (mountable->exec);
+ g_free (mountable->dbus_name);
+ g_free (mountable->scheme);
+ g_strfreev (mountable->scheme_aliases);
+ g_free (mountable);
+}
+
+static void
+vfs_mount_free (VfsMount *mount)
+{
+ g_free (mount->display_name);
+ g_free (mount->stable_name);
+ g_free (mount->x_content_types);
+ g_free (mount->icon);
+ g_free (mount->fuse_mountpoint);
+ g_free (mount->prefered_filename_encoding);
+ g_free (mount->dbus_id);
+ g_free (mount->object_path);
+ g_mount_spec_unref (mount->mount_spec);
+
+ g_free (mount);
+}
+
+static void
+vfs_mount_to_dbus (VfsMount *mount,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter struct_iter;
+ dbus_bool_t user_visible;
+ char *fuse_mountpoint;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->dbus_id))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_OBJECT_PATH,
+ &mount->object_path))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->display_name))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->stable_name))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->x_content_types))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->icon))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mount->prefered_filename_encoding))
+ _g_dbus_oom ();
+
+ user_visible = mount->user_visible;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_BOOLEAN,
+ &user_visible))
+ _g_dbus_oom ();
+
+
+ fuse_mountpoint = "";
+ if (fuse_available && mount->fuse_mountpoint)
+ fuse_mountpoint = mount->fuse_mountpoint;
+ _g_dbus_message_iter_append_cstring (&struct_iter, fuse_mountpoint);
+
+ g_mount_spec_to_dbus (&struct_iter, mount->mount_spec);
+
+ if (!dbus_message_iter_close_container (iter, &struct_iter))
+ _g_dbus_oom ();
+}
+
+static void
+vfs_mountable_to_dbus (VfsMountable *mountable,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter struct_iter;
+ dbus_bool_t bool;
+ guint32 int32;
+ char *s;
+ char **a;
+ char *empty[] = {NULL};
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &mountable->type))
+ _g_dbus_oom ();
+
+ s = mountable->scheme;
+ if (s == NULL)
+ s = "";
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &s))
+ _g_dbus_oom ();
+
+ a = mountable->scheme_aliases;
+ if (a == NULL)
+ a = empty;
+ _g_dbus_message_iter_append_args (&struct_iter,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &a, (int)g_strv_length (a),
+ 0);
+
+ int32 = mountable->default_port;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_INT32,
+ &int32))
+ _g_dbus_oom ();
+
+ bool = mountable->hostname_is_inet;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_BOOLEAN,
+ &bool))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &struct_iter))
+ _g_dbus_oom ();
+}
+
+
+/************************************************************************
+ * Support for mounting a VfsMountable *
+ ************************************************************************/
+
+
+typedef struct {
+ VfsMountable *mountable;
+ dbus_bool_t automount;
+ GMountSource *source;
+ GMountSpec *mount_spec;
+ MountCallback callback;
+ gpointer user_data;
+ char *obj_path;
+ gboolean spawned;
+} MountData;
+
+static void spawn_mount (MountData *data);
+
+static void
+mount_data_free (MountData *data)
+{
+ g_object_unref (data->source);
+ g_mount_spec_unref (data->mount_spec);
+ g_free (data->obj_path);
+
+ g_free (data);
+}
+
+static void
+mount_finish (MountData *data, GError *error)
+{
+ data->callback (data->mountable, error, data->user_data);
+ mount_data_free (data);
+}
+
+static void
+dbus_mount_reply (DBusPendingCall *pending,
+ void *_data)
+{
+ DBusMessage *reply;
+ GError *error;
+ MountData *data = _data;
+
+ reply = dbus_pending_call_steal_reply (pending);
+ dbus_pending_call_unref (pending);
+
+ if ((dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) ||
+ dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) &&
+ !data->spawned)
+ spawn_mount (data);
+ else
+ {
+ error = NULL;
+ if (_g_error_from_message (reply, &error))
+ {
+ mount_finish (data, error);
+ g_error_free (error);
+ }
+ else
+ mount_finish (data, NULL);
+ }
+
+ dbus_message_unref (reply);
+}
+
+static void
+mountable_mount_with_name (MountData *data,
+ const char *dbus_name)
+{
+ DBusConnection *conn;
+ DBusMessage *message;
+ DBusPendingCall *pending;
+ GError *error = NULL;
+ DBusMessageIter iter;
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ message = dbus_message_new_method_call (dbus_name,
+ G_VFS_DBUS_MOUNTABLE_PATH,
+ G_VFS_DBUS_MOUNTABLE_INTERFACE,
+ G_VFS_DBUS_MOUNTABLE_OP_MOUNT);
+
+ dbus_message_iter_init_append (message, &iter);
+ g_mount_spec_to_dbus (&iter, data->mount_spec);
+
+ _g_dbus_message_append_args (message,
+ DBUS_TYPE_BOOLEAN, &data->automount,
+ 0);
+
+ g_mount_source_to_dbus (data->source, message);
+
+ if (!dbus_connection_send_with_reply (conn, message,
+ &pending,
+ G_VFS_DBUS_MOUNT_TIMEOUT_MSECS))
+ _g_dbus_oom ();
+
+ dbus_message_unref (message);
+ dbus_connection_unref (conn);
+
+ if (pending == NULL)
+ {
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ "Connection is closed");
+ mount_finish (data, error);
+ g_error_free (error);
+ return;
+ }
+
+ if (!dbus_pending_call_set_notify (pending,
+ dbus_mount_reply,
+ data, NULL))
+ _g_dbus_oom ();
+}
+
+static DBusHandlerResult
+spawn_mount_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ MountData *data = user_data;
+ GError *error = NULL;
+ dbus_bool_t succeeded;
+ char *error_message;
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_SPAWNER_INTERFACE,
+ G_VFS_DBUS_OP_SPAWNED))
+ {
+ dbus_connection_unregister_object_path (connection, data->obj_path);
+
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_BOOLEAN, &succeeded,
+ DBUS_TYPE_STRING, &error_message,
+ DBUS_TYPE_INVALID))
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid arguments from spawned child"));
+ mount_finish (data, error);
+ g_error_free (error);
+ }
+ else if (!succeeded)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, error_message);
+ mount_finish (data, error);
+ g_error_free (error);
+ }
+ else
+ mountable_mount_with_name (data, dbus_message_get_sender (message));
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+spawn_mount (MountData *data)
+{
+ char *exec;
+ GError *error;
+ DBusConnection *connection;
+ static int mount_id = 0;
+ DBusObjectPathVTable spawn_vtable = {
+ NULL,
+ spawn_mount_message_function
+ };
+
+ data->spawned = TRUE;
+
+ error = NULL;
+ if (data->mountable->exec == NULL)
+ {
+ g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No exec key defined for mountpoint");
+ mount_finish (data, error);
+ g_error_free (error);
+ }
+ else
+ {
+ data->obj_path = g_strdup_printf ("/org/gtk/gvfs/exec_spaw/%d", mount_id++);
+
+ connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (!dbus_connection_register_object_path (connection,
+ data->obj_path,
+ &spawn_vtable,
+ data))
+ _g_dbus_oom ();
+
+ exec = g_strconcat (data->mountable->exec, " --spawner ", dbus_bus_get_unique_name (connection), " ", data->obj_path, NULL);
+
+ if (!g_spawn_command_line_async (exec, &error))
+ {
+ dbus_connection_unregister_object_path (connection, data->obj_path);
+ mount_finish (data, error);
+ g_error_free (error);
+ }
+
+ /* TODO: Add a timeout here to detect spawned app crashing */
+
+ dbus_connection_unref (connection);
+ g_free (exec);
+ }
+}
+
+static void
+mountable_mount (VfsMountable *mountable,
+ GMountSpec *mount_spec,
+ GMountSource *source,
+ gboolean automount,
+ MountCallback callback,
+ gpointer user_data)
+{
+ MountData *data;
+
+ data = g_new0 (MountData, 1);
+ data->automount = automount;
+ data->mountable = mountable;
+ data->source = g_object_ref (source);
+ data->mount_spec = g_mount_spec_ref (mount_spec);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (mountable->dbus_name == NULL)
+ spawn_mount (data);
+ else
+ mountable_mount_with_name (data, mountable->dbus_name);
+}
+
+static void
+read_mountable_config (void)
+{
+ GDir *dir;
+ char *mount_dir, *path;
+ const char *filename;
+ GKeyFile *keyfile;
+ char **types;
+ VfsMountable *mountable;
+ int i;
+
+ mount_dir = MOUNTABLE_DIR;
+ dir = g_dir_open (mount_dir, 0, NULL);
+
+ if (dir)
+ {
+ while ((filename = g_dir_read_name (dir)) != NULL)
+ {
+ path = g_build_filename (mount_dir, filename, NULL);
+
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL))
+ {
+ types = g_key_file_get_string_list (keyfile, "Mount", "Type", NULL, NULL);
+ if (types != NULL)
+ {
+ for (i = 0; types[i] != NULL; i++)
+ {
+ if (*types[i] != 0)
+ {
+ mountable = g_new0 (VfsMountable, 1);
+ mountable->type = g_strdup (types[i]);
+ mountable->exec = g_key_file_get_string (keyfile, "Mount", "Exec", NULL);
+ mountable->dbus_name = g_key_file_get_string (keyfile, "Mount", "DBusName", NULL);
+ mountable->automount = g_key_file_get_boolean (keyfile, "Mount", "AutoMount", NULL);
+ mountable->scheme = g_key_file_get_string (keyfile, "Mount", "Scheme", NULL);
+ mountable->scheme_aliases =
+ g_key_file_get_string_list (keyfile, "Mount", "SchemeAliases", NULL, NULL);
+ mountable->default_port = g_key_file_get_integer (keyfile, "Mount", "DefaultPort", NULL);
+ mountable->hostname_is_inet = g_key_file_get_boolean (keyfile, "Mount", "HostnameIsInetAddress", NULL);
+
+ if (mountable->scheme == NULL)
+ mountable->scheme = g_strdup (mountable->type);
+
+ mountables = g_list_prepend (mountables, mountable);
+ }
+ }
+ g_strfreev (types);
+ }
+ }
+ g_key_file_free (keyfile);
+ g_free (path);
+ }
+ g_dir_close (dir);
+ }
+}
+
+static void
+re_read_mountable_config (void)
+{
+ g_list_foreach (mountables, (GFunc)vfs_mountable_free, NULL);
+ g_list_free (mountables);
+ mountables = NULL;
+
+ read_mountable_config ();
+}
+
+/************************************************************************
+ * Support for keeping track of active mounts *
+ ************************************************************************/
+
+static void
+signal_mounted_unmounted (VfsMount *mount,
+ gboolean mounted)
+{
+ DBusMessage *message;
+ DBusMessageIter iter;
+ DBusConnection *conn;
+
+ message = dbus_message_new_signal (G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ mounted ?
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED :
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED
+ );
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_iter_init_append (message, &iter);
+ vfs_mount_to_dbus (mount, &iter);
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ dbus_connection_send (conn, message, NULL);
+ dbus_connection_unref (conn);
+
+ dbus_message_unref (message);
+}
+
+static void
+dbus_client_disconnected (const char *dbus_id)
+{
+ GList *l, *next;
+
+ next = NULL;
+ for (l = mounts; l != NULL; l = next)
+ {
+ VfsMount *mount = l->data;
+ next = l->next;
+
+ if (strcmp (mount->dbus_id, dbus_id) == 0)
+ {
+ signal_mounted_unmounted (mount, FALSE);
+
+ vfs_mount_free (mount);
+ mounts = g_list_delete_link (mounts, l);
+ }
+ }
+}
+
+static void
+register_mount (DBusConnection *connection,
+ DBusMessage *message)
+{
+ VfsMount *mount;
+ DBusMessage *reply;
+ DBusError error;
+ const char *display_name, *stable_name, *x_content_types, *icon, *obj_path, *id, *prefered_filename_encoding;
+ dbus_bool_t user_visible;
+ DBusMessageIter iter;
+ GMountSpec *mount_spec;
+
+ id = dbus_message_get_sender (message);
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&error);
+ if (_g_dbus_message_iter_get_args (&iter,
+ &error,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ DBUS_TYPE_STRING, &display_name,
+ DBUS_TYPE_STRING, &stable_name,
+ DBUS_TYPE_STRING, &x_content_types,
+ DBUS_TYPE_STRING, &icon,
+ DBUS_TYPE_STRING, &prefered_filename_encoding,
+ DBUS_TYPE_BOOLEAN, &user_visible,
+ 0))
+ {
+ if (find_vfs_mount (id, obj_path) != NULL)
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Mountpoint Already registered");
+ else if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL)
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Error in mount spec");
+ else if (match_vfs_mount (mount_spec) != NULL)
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Mountpoint Already registered");
+ else
+ {
+ mount = g_new0 (VfsMount, 1);
+ mount->display_name = g_strdup (display_name);
+ mount->stable_name = g_strdup (stable_name);
+ mount->x_content_types = g_strdup (x_content_types);
+ mount->icon = g_strdup (icon);
+ mount->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
+ mount->user_visible = user_visible;
+ mount->dbus_id = g_strdup (id);
+ mount->object_path = g_strdup (obj_path);
+ mount->mount_spec = mount_spec;
+
+ if (user_visible)
+ {
+ char *fs_name;
+
+ /* Keep in sync with fuse daemon */
+ fs_name = g_uri_escape_string (mount->stable_name, "+@#$., ", TRUE);
+
+ mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL);
+ }
+
+ mounts = g_list_prepend (mounts, mount);
+
+ signal_mounted_unmounted (mount, TRUE);
+
+ reply = dbus_message_new_method_return (message);
+ }
+ }
+ else
+ {
+ reply = dbus_message_new_error (message,
+ error.name, error.message);
+ dbus_error_free (&error);
+ }
+
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ dbus_connection_send (connection, reply, NULL);
+}
+
+typedef struct {
+ DBusMessage *message;
+ DBusConnection *connection;
+} AutoMountData;
+
+static void
+automount_done (VfsMountable *mountable,
+ GError *error,
+ gpointer _data)
+{
+ DBusMessage *reply;
+ AutoMountData *data = _data;
+
+ if (error)
+ {
+ reply = _dbus_message_new_gerror (data->message,
+ G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
+ _("Automount failed: %s"), error->message);
+ dbus_connection_send (data->connection, reply, NULL);
+ }
+ else
+ lookup_mount (data->connection,
+ data->message,
+ FALSE);
+
+ dbus_connection_unref (data->connection);
+ dbus_message_unref (data->message);
+ g_free (data);
+}
+
+static DBusMessage *
+maybe_automount (GMountSpec *spec,
+ DBusMessage *message,
+ DBusConnection *connection,
+ gboolean do_automount)
+{
+ VfsMountable *mountable;
+ DBusMessage *reply;
+
+ mountable = lookup_mountable (spec);
+
+ reply = NULL;
+ if (mountable != NULL && do_automount && mountable->automount)
+ {
+ AutoMountData *data;
+ GMountSource *mount_source;
+
+ g_debug ("automounting...\n");
+
+ mount_source = g_mount_source_new_dummy ();
+
+ data = g_new0 (AutoMountData, 1);
+ data->message = dbus_message_ref (message);
+ data->connection = dbus_connection_ref (connection);
+
+ mountable_mount (mountable, spec, mount_source, TRUE, automount_done, data);
+ g_object_unref (mount_source);
+ }
+ else if (mountable != NULL)
+ reply = _dbus_message_new_gerror (message,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_MOUNTED,
+ _("The specified location is not mounted"));
+ else
+ reply = _dbus_message_new_gerror (message,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("The specified location is not supported"));
+
+ return reply;
+}
+
+static void
+lookup_mount (DBusConnection *connection,
+ DBusMessage *message,
+ gboolean do_automount)
+{
+ VfsMount *mount;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ GMountSpec *spec;
+
+ dbus_message_iter_init (message, &iter);
+ spec = g_mount_spec_from_dbus (&iter);
+
+ reply = NULL;
+ if (spec != NULL)
+ {
+ mount = match_vfs_mount (spec);
+
+ if (mount == NULL)
+ reply = maybe_automount (spec, message, connection, do_automount);
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+
+ if (reply)
+ {
+ dbus_message_iter_init_append (reply, &iter);
+
+ vfs_mount_to_dbus (mount, &iter);
+ }
+ }
+ }
+ else
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Invalid arguments");
+
+ g_mount_spec_unref (spec);
+ if (reply != NULL)
+ dbus_connection_send (connection, reply, NULL);
+}
+
+static void
+lookup_mount_by_fuse_path (DBusConnection *connection,
+ DBusMessage *message)
+{
+ VfsMount *mount;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ char *fuse_path;
+
+ dbus_message_iter_init (message, &iter);
+
+ reply = NULL;
+ if (_g_dbus_message_iter_get_args (&iter, NULL,
+ G_DBUS_TYPE_CSTRING, &fuse_path,
+ 0))
+ {
+ mount = find_vfs_mount_by_fuse_path (fuse_path);
+
+ if (mount == NULL)
+ reply = _dbus_message_new_gerror (message,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_MOUNTED,
+ _("The specified location is not mounted"));
+ else
+ {
+ reply = dbus_message_new_method_return (message);
+ if (reply)
+ {
+ dbus_message_iter_init_append (reply, &iter);
+ vfs_mount_to_dbus (mount, &iter);
+ }
+ }
+ }
+ else
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "Invalid arguments");
+
+ if (reply != NULL)
+ dbus_connection_send (connection, reply, NULL);
+}
+
+static void
+list_mounts (DBusConnection *connection,
+ DBusMessage *message)
+{
+ VfsMount *mount;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ GList *l;
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_iter_init_append (reply, &iter);
+
+
+ if (!dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_OBJECT_PATH_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_BOOLEAN_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
+ G_MOUNT_SPEC_TYPE_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ mount = l->data;
+
+ vfs_mount_to_dbus (mount, &array_iter);
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &array_iter))
+ _g_dbus_oom ();
+
+ dbus_connection_send (connection, reply, NULL);
+}
+
+static void
+mount_location_done (VfsMountable *mountable,
+ GError *error,
+ gpointer user_data)
+{
+ DBusMessage *message, *reply;
+ DBusConnection *conn;
+
+ message = user_data;
+
+ if (error)
+ reply = _dbus_message_new_from_gerror (message, error);
+ else
+ reply = dbus_message_new_method_return (message);
+
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+ if (conn)
+ {
+ dbus_connection_send (conn, reply, NULL);
+ dbus_connection_unref (conn);
+ }
+
+ dbus_message_unref (reply);
+}
+
+static void
+mount_location (DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError derror;
+ GMountSpec *spec;
+ const char *obj_path, *dbus_id;
+ VfsMountable *mountable;
+
+ dbus_message_iter_init (message, &iter);
+
+ mountable = NULL;
+ spec = NULL;
+ reply = NULL;
+
+ spec = g_mount_spec_from_dbus (&iter);
+ if (spec == NULL)
+ reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid arguments");
+ else
+ {
+ dbus_error_init (&derror);
+ if (!_g_dbus_message_iter_get_args (&iter,
+ &derror,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ 0))
+ {
+ reply = dbus_message_new_error (message, derror.name, derror.message);
+ dbus_error_free (&derror);
+ }
+ else
+ {
+ VfsMount *mount;
+ mount = match_vfs_mount (spec);
+
+ if (mount != NULL)
+ reply = _dbus_message_new_gerror (message,
+ G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED,
+ _("Location is already mounted"));
+ else
+ {
+ mountable = lookup_mountable (spec);
+
+ if (mountable == NULL)
+ reply = _dbus_message_new_gerror (message,
+ G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
+ _("Location is not mountable"));
+ }
+ }
+ }
+
+ if (reply)
+ dbus_connection_send (connection, reply, NULL);
+ else
+ {
+ GMountSource *source;
+
+ source = g_mount_source_new (dbus_id, obj_path);
+ mountable_mount (mountable,
+ spec,
+ source,
+ FALSE,
+ mount_location_done, dbus_message_ref (message));
+ g_object_unref (source);
+ }
+
+ if (spec)
+ g_mount_spec_unref (spec);
+
+}
+
+static void
+list_mount_types (DBusConnection *connection,
+ DBusMessage *message)
+{
+ VfsMountable *mountable;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ GList *l;
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_iter_init_append (reply, &iter);
+
+
+ if (!dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (l = mountables; l != NULL; l = l->next)
+ {
+ mountable = l->data;
+ if (!dbus_message_iter_append_basic (&array_iter,
+ DBUS_TYPE_STRING,
+ &mountable->type))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &array_iter))
+ _g_dbus_oom ();
+
+ dbus_connection_send (connection, reply, NULL);
+}
+
+static void
+list_mountable_info (DBusConnection *connection,
+ DBusMessage *message)
+{
+ VfsMountable *mountable;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ GList *l;
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_iter_init_append (reply, &iter);
+
+
+ if (!dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING /* type */
+ DBUS_TYPE_STRING_AS_STRING /* scheme */
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING /* scheme aliases */
+ DBUS_TYPE_INT32_AS_STRING /* default port */
+ DBUS_TYPE_BOOLEAN_AS_STRING /* host is inet */
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (l = mountables; l != NULL; l = l->next)
+ {
+ mountable = l->data;
+
+ vfs_mountable_to_dbus (mountable, &array_iter);
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &array_iter))
+ _g_dbus_oom ();
+
+ dbus_connection_send (connection, reply, NULL);
+}
+
+static DBusHandlerResult
+dbus_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ DBusHandlerResult res;
+
+ res = DBUS_HANDLER_RESULT_HANDLED;
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE))
+ fuse_available = TRUE;
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT))
+ register_mount (connection, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT))
+ lookup_mount (connection, message, TRUE);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH))
+ lookup_mount_by_fuse_path (connection, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS))
+ list_mounts (connection, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION))
+ mount_location (connection, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES))
+ list_mount_types (connection, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO))
+ list_mountable_info (connection, message);
+ else
+ res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ return res;
+}
+
+struct DBusObjectPathVTable tracker_dbus_vtable = {
+ NULL,
+ dbus_message_function
+};
+
+
+static DBusHandlerResult
+mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ const char *name, *from, *to;
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ if (dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &from,
+ DBUS_TYPE_STRING, &to,
+ DBUS_TYPE_INVALID))
+ {
+ if (*name == ':' && *to == 0)
+ dbus_client_disconnected (name);
+ }
+
+ }
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static int reload_pipes[2];
+
+static void
+sigusr1_handler (int sig)
+{
+ while (write (reload_pipes[1], "a", 1) != 1)
+ ;
+}
+
+static gboolean
+reload_pipes_cb (GIOChannel *io,
+ GIOCondition condition,
+ gpointer data)
+{
+ char a;
+
+ while (read (reload_pipes[0], &a, 1) != 1)
+ ;
+
+ re_read_mountable_config ();
+
+ return TRUE;
+}
+
+void
+mount_init (void)
+{
+ DBusConnection *conn;
+ DBusError error;
+ struct sigaction sa;
+ GIOChannel *io;
+
+ read_mountable_config ();
+
+ if (pipe (reload_pipes) != -1)
+ {
+ io = g_io_channel_unix_new (reload_pipes[0]);
+ g_io_add_watch (io, G_IO_IN, reload_pipes_cb, NULL);
+
+ sa.sa_handler = sigusr1_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction (SIGUSR1, &sa, NULL);
+ }
+
+ conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+
+ if (!dbus_connection_register_object_path (conn, G_VFS_DBUS_MOUNTTRACKER_PATH,
+ &tracker_dbus_vtable, NULL))
+ _g_dbus_oom ();
+
+ if (!dbus_connection_add_filter (conn,
+ mount_tracker_filter_func, NULL, NULL))
+ _g_dbus_oom ();
+
+
+ dbus_error_init (&error);
+ dbus_bus_add_match (conn,
+ "sender='org.freedesktop.DBus',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged'",
+ &error);
+ if (dbus_error_is_set (&error))
+ {
+ g_warning ("Failed to add dbus match: %s\n", error.message);
+ dbus_error_free (&error);
+ }
+}
+
diff --git a/trunk/daemon/mount.h b/trunk/daemon/mount.h
new file mode 100644
index 00000000..ff244b5b
--- /dev/null
+++ b/trunk/daemon/mount.h
@@ -0,0 +1,37 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __MOUNT_H__
+#define __MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gmountsource.h>
+
+G_BEGIN_DECLS
+
+void mount_init (void);
+
+G_END_DECLS
+
+#endif /* __MOUNT_H__ */
+
diff --git a/trunk/daemon/network.mount.in b/trunk/daemon/network.mount.in
new file mode 100644
index 00000000..4e02907d
--- /dev/null
+++ b/trunk/daemon/network.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=network
+Exec=@libexecdir@/gvfsd-network
+AutoMount=true
diff --git a/trunk/daemon/obexftp-marshal.list b/trunk/daemon/obexftp-marshal.list
new file mode 100644
index 00000000..676e2af3
--- /dev/null
+++ b/trunk/daemon/obexftp-marshal.list
@@ -0,0 +1,5 @@
+VOID:STRING
+VOID:UINT64
+VOID:STRING,STRING
+VOID:STRING,STRING,STRING
+VOID:STRING,STRING,UINT64
diff --git a/trunk/daemon/obexftp.mount.in b/trunk/daemon/obexftp.mount.in
new file mode 100644
index 00000000..96ade114
--- /dev/null
+++ b/trunk/daemon/obexftp.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=obex
+Exec=@libexecdir@/gvfsd-obexftp
+AutoMount=false
diff --git a/trunk/daemon/pty_open.c b/trunk/daemon/pty_open.c
new file mode 100644
index 00000000..6f6d83e8
--- /dev/null
+++ b/trunk/daemon/pty_open.c
@@ -0,0 +1,843 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/*
+ * Copyright (C) 2001,2002,2004 Red Hat, Inc.
+ *
+ * This 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 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 Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Originally from vte */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#include <glib.h>
+#include "pty_open.h"
+
+int _pty_set_size(int master, int columns, int rows);
+
+/* Solaris does not have the login_tty() function so implement locally. */
+#ifndef HAVE_LOGIN_TTY
+static int login_tty(int pts)
+{
+#if defined(HAVE_STROPTS_H)
+ /* push a terminal onto stream head */
+ if (ioctl(pts, I_PUSH, "ptem") == -1) return -1;
+ if (ioctl(pts, I_PUSH, "ldterm") == -1) return -1;
+#endif
+ setsid();
+#if defined(TIOCSCTTY)
+ ioctl(pts, TIOCSCTTY, 0);
+#endif
+ dup2(pts, 0);
+ dup2(pts, 1);
+ dup2(pts, 2);
+ if (pts > 2) close(pts);
+ return 0;
+}
+#endif
+
+/* Reset the handlers for all known signals to their defaults. The parent
+ * (or one of the libraries it links to) may have changed one to be ignored. */
+static void
+_pty_reset_signal_handlers(void)
+{
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
+ signal(SIGABRT, SIG_DFL);
+ signal(SIGFPE, SIG_DFL);
+ signal(SIGKILL, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
+ signal(SIGALRM, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGCONT, SIG_DFL);
+ signal(SIGSTOP, SIG_DFL);
+ signal(SIGTSTP, SIG_DFL);
+ signal(SIGTTIN, SIG_DFL);
+ signal(SIGTTOU, SIG_DFL);
+#ifdef SIGBUS
+ signal(SIGBUS, SIG_DFL);
+#endif
+#ifdef SIGPOLL
+ signal(SIGPOLL, SIG_DFL);
+#endif
+#ifdef SIGPROF
+ signal(SIGPROF, SIG_DFL);
+#endif
+#ifdef SIGSYS
+ signal(SIGSYS, SIG_DFL);
+#endif
+#ifdef SIGTRAP
+ signal(SIGTRAP, SIG_DFL);
+#endif
+#ifdef SIGURG
+ signal(SIGURG, SIG_DFL);
+#endif
+#ifdef SIGVTALARM
+ signal(SIGVTALARM, SIG_DFL);
+#endif
+#ifdef SIGXCPU
+ signal(SIGXCPU, SIG_DFL);
+#endif
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_DFL);
+#endif
+#ifdef SIGIOT
+ signal(SIGIOT, SIG_DFL);
+#endif
+#ifdef SIGEMT
+ signal(SIGEMT, SIG_DFL);
+#endif
+#ifdef SIGSTKFLT
+ signal(SIGSTKFLT, SIG_DFL);
+#endif
+#ifdef SIGIO
+ signal(SIGIO, SIG_DFL);
+#endif
+#ifdef SIGCLD
+ signal(SIGCLD, SIG_DFL);
+#endif
+#ifdef SIGPWR
+ signal(SIGPWR, SIG_DFL);
+#endif
+#ifdef SIGINFO
+ signal(SIGINFO, SIG_DFL);
+#endif
+#ifdef SIGLOST
+ signal(SIGLOST, SIG_DFL);
+#endif
+#ifdef SIGWINCH
+ signal(SIGWINCH, SIG_DFL);
+#endif
+#ifdef SIGUNUSED
+ signal(SIGUNUSED, SIG_DFL);
+#endif
+}
+
+#ifdef HAVE_SOCKETPAIR
+static int
+_pty_pipe_open(int *a, int *b)
+{
+ int p[2], ret = -1;
+#ifdef PF_UNIX
+#ifdef SOCK_STREAM
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, p);
+#else
+#ifdef SOCK_DGRAM
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, p);
+#endif
+#endif
+ if (ret == 0) {
+ *a = p[0];
+ *b = p[1];
+ return 0;
+ }
+#endif
+ return ret;
+}
+#else
+static int
+_pty_pipe_open(int *a, int *b)
+{
+ int p[2], ret = -1;
+
+ ret = pipe(p);
+
+ if (ret == 0) {
+ *a = p[0];
+ *b = p[1];
+ }
+ return ret;
+}
+#endif
+
+static int
+_pty_pipe_open_bi(int *a, int *b, int *c, int *d)
+{
+ int ret;
+ ret = _pty_pipe_open(a, b);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = _pty_pipe_open(c, d);
+ if (ret != 0) {
+ close(*a);
+ close(*b);
+ }
+ return ret;
+}
+
+/* Like read, but hide EINTR and EAGAIN. */
+static ssize_t
+n_read(int fd, void *buffer, size_t count)
+{
+ size_t n = 0;
+ char *buf = buffer;
+ int i;
+ while (n < count) {
+ i = read(fd, buf + n, count - n);
+ switch (i) {
+ case 0:
+ return n;
+ break;
+ case -1:
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+#ifdef ERESTART
+ case ERESTART:
+#endif
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ n += i;
+ break;
+ }
+ }
+ return n;
+}
+
+/* Like write, but hide EINTR and EAGAIN. */
+static ssize_t
+n_write(int fd, const void *buffer, size_t count)
+{
+ size_t n = 0;
+ const char *buf = buffer;
+ int i;
+ while (n < count) {
+ i = write(fd, buf + n, count - n);
+ switch (i) {
+ case 0:
+ return n;
+ break;
+ case -1:
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+#ifdef ERESTART
+ case ERESTART:
+#endif
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ n += i;
+ break;
+ }
+ }
+ return n;
+}
+
+/* Run the given command (if specified), using the given descriptor as the
+ * controlling terminal. */
+static int
+_pty_run_on_pty(int fd, gboolean login,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ int ready_reader, int ready_writer,
+ char **env_add, const char *command, char **argv,
+ const char *directory)
+{
+ int i;
+ char c;
+ char **args, *arg;
+
+#ifdef HAVE_STROPTS_H
+ if (!ioctl (fd, I_FIND, "ptem") && ioctl (fd, I_PUSH, "ptem") == -1) {
+ close (fd);
+ _exit (0);
+ return -1;
+ }
+
+ if (!ioctl (fd, I_FIND, "ldterm") && ioctl (fd, I_PUSH, "ldterm") == -1) {
+ close (fd);
+ _exit (0);
+ return -1;
+ }
+
+ if (!ioctl (fd, I_FIND, "ttcompat") && ioctl (fd, I_PUSH, "ttcompat") == -1) {
+ perror ("ioctl (fd, I_PUSH, \"ttcompat\")");
+ close (fd);
+ _exit (0);
+ return -1;
+ }
+#endif /* HAVE_STROPTS_H */
+
+ /* Set any environment variables. */
+ for (i = 0; (env_add != NULL) && (env_add[i] != NULL); i++) {
+ if (putenv(g_strdup(env_add[i])) != 0) {
+ g_warning("Error adding `%s' to environment, "
+ "continuing.", env_add[i]);
+ }
+ }
+
+ /* Reset our signals -- our parent may have done any number of
+ * weird things to them. */
+ _pty_reset_signal_handlers();
+
+ /* Change to the requested directory. */
+ if (directory != NULL) {
+ chdir(directory);
+ }
+
+#ifdef HAVE_UTMP_H
+ /* This sets stdin, stdout, stderr to the socket */
+ if (login && login_tty (fd) == -1) {
+ g_printerr ("mount child process login_tty failed: %s\n", g_strerror (errno));
+ return -1;
+ }
+#endif
+
+ /* Signal to the parent that we've finished setting things up by
+ * sending an arbitrary byte over the status pipe and waiting for
+ * a response. This synchronization step ensures that the pty is
+ * fully initialized before the parent process attempts to do anything
+ * with it, and is required on systems where additional setup, beyond
+ * merely opening the device, is required. This is at least the case
+ * on Solaris. */
+ /* Initialize so valgrind doesn't complain */
+ c = 0;
+ n_write(ready_writer, &c, 1);
+ fsync(ready_writer);
+ n_read(ready_reader, &c, 1);
+ close(ready_writer);
+ if (ready_writer != ready_reader) {
+ close(ready_reader);
+ }
+
+ /* If the caller provided a command, we can't go back, ever. */
+ if (command != NULL) {
+ /* Outta here. */
+ if (argv != NULL) {
+ for (i = 0; (argv[i] != NULL); i++) ;
+ args = g_malloc0(sizeof(char*) * (i + 1));
+ for (i = 0; (argv[i] != NULL); i++) {
+ args[i] = g_strdup(argv[i]);
+ }
+ execvp(command, args);
+ } else {
+ arg = g_strdup(command);
+ execlp(command, arg, NULL);
+ }
+
+ /* Avoid calling any atexit() code. */
+ _exit(0);
+ g_assert_not_reached();
+ }
+
+ return 0;
+}
+
+/* Open the named PTY slave, fork off a child (storing its PID in child),
+ * and exec the named command in its own session as a process group leader */
+static int
+_pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
+ const char *command, char **argv,
+ const char *directory,
+ int columns, int rows,
+ int *stdin_fd, int *stdout_fd, int *stderr_fd,
+ pid_t *child, gboolean reapchild, gboolean login)
+{
+ int fd, i;
+ char c;
+ int ready_a[2] = { 0, 0 };
+ int ready_b[2] = { 0, 0 };
+ pid_t pid, grandchild_pid;
+ int pid_pipe[2];
+ int stdin_pipe[2];
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+
+ /* Open pipes for synchronizing between parent and child. */
+ if (_pty_pipe_open_bi(&ready_a[0], &ready_a[1],
+ &ready_b[0], &ready_b[1]) == -1) {
+ /* Error setting up pipes. Bail. */
+ goto bail_ready;
+ }
+
+ if (reapchild && pipe(pid_pipe)) {
+ /* Error setting up pipes. Bail. */
+ goto bail_pid;
+ }
+
+ if (pipe(stdin_pipe)) {
+ /* Error setting up pipes. Bail. */
+ goto bail_stdin;
+ }
+ if (pipe(stdout_pipe)) {
+ /* Error setting up pipes. Bail. */
+ goto bail_stdout;
+ }
+ if (pipe(stderr_pipe)) {
+ /* Error setting up pipes. Bail. */
+ goto bail_stderr;
+ }
+
+ /* Start up a child. */
+ pid = fork();
+ switch (pid) {
+ case -1:
+ /* Error fork()ing. Bail. */
+ *child = -1;
+ return -1;
+ break;
+ case 0:
+ /* Child. Close the parent's ends of the pipes. */
+ close(ready_a[0]);
+ close(ready_b[1]);
+
+ close(stdin_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stderr_pipe[0]);
+
+ if(reapchild) {
+ close(pid_pipe[0]);
+
+ /* Fork a intermediate child. This is needed to not
+ * produce zombies! */
+ grandchild_pid = fork();
+
+ if (grandchild_pid < 0) {
+ /* Error during fork! */
+ n_write (pid_pipe[1], &grandchild_pid,
+ sizeof (grandchild_pid));
+ _exit (1);
+ } else if (grandchild_pid > 0) {
+ /* Parent! (This is the actual intermediate child;
+ * so write the pid to the parent and then exit */
+ n_write (pid_pipe[1], &grandchild_pid,
+ sizeof (grandchild_pid));
+ close (pid_pipe[1]);
+ _exit (0);
+ }
+
+ /* Start a new session and become process-group leader. */
+ setsid();
+ setpgid(0, 0);
+ }
+
+ /* Close most descriptors. */
+ for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
+ if ((i != ready_b[0]) &&
+ (i != ready_a[1]) &&
+ (i != stdin_pipe[0]) &&
+ (i != stdout_pipe[1]) &&
+ (i != stderr_pipe[1])) {
+ close(i);
+ }
+ }
+
+ /* Set up stdin/out/err */
+ dup2(stdin_pipe[0], STDIN_FILENO);
+ close (stdin_pipe[0]);
+ dup2(stdout_pipe[1], STDOUT_FILENO);
+ close (stdout_pipe[1]);
+ dup2(stderr_pipe[1], STDERR_FILENO);
+ close (stderr_pipe[1]);
+
+ /* Open the slave PTY, acquiring it as the controlling terminal
+ * for this process and its children. */
+ fd = open(path, O_RDWR);
+ if (fd == -1) {
+ return -1;
+ }
+#ifdef TIOCSCTTY
+ /* TIOCSCTTY is defined? Let's try that, too. */
+ ioctl(fd, TIOCSCTTY, fd);
+#endif
+ /* Store 0 as the "child"'s ID to indicate to the caller that
+ * it is now the child. */
+ *child = 0;
+ return _pty_run_on_pty(fd, login,
+ stdin_pipe[1], stdout_pipe[1], stderr_pipe[1],
+ ready_b[0], ready_a[1],
+ env_add, command, argv, directory);
+ break;
+ default:
+ /* Parent. Close the child's ends of the pipes, do the ready
+ * handshake, and return the child's PID. */
+ close(ready_b[0]);
+ close(ready_a[1]);
+
+ close(stdin_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[1]);
+
+ if (reapchild) {
+ close(pid_pipe[1]);
+
+ /* Reap the intermediate child */
+ wait_again:
+ if (waitpid (pid, NULL, 0) < 0) {
+ if (errno == EINTR) {
+ goto wait_again;
+ } else if (errno == ECHILD) {
+ ; /* NOOP! Child already reaped. */
+ } else {
+ g_warning ("waitpid() should not fail in pty-open.c");
+ }
+ }
+
+ /*
+ * Read the child pid from the pid_pipe
+ * */
+ if (n_read (pid_pipe[0], child, sizeof (pid_t))
+ != sizeof (pid_t) || *child == -1) {
+ g_warning ("Error while spanning child!");
+ goto bail_fork;
+ }
+
+ close(pid_pipe[0]);
+
+ } else {
+ /* No intermediate child, simple */
+ *child = pid;
+ }
+
+ /* Wait for the child to be ready, set the window size, then
+ * signal that we're ready. We need to synchronize here to
+ * avoid possible races when the child has to do more setup
+ * of the terminal than just opening it. */
+ n_read(ready_a[0], &c, 1);
+ _pty_set_size(parent_fd, columns, rows);
+ n_write(ready_b[1], &c, 1);
+ close(ready_a[0]);
+ close(ready_b[1]);
+
+ *stdin_fd = stdin_pipe[1];
+ *stdout_fd = stdout_pipe[0];
+ *stderr_fd = stderr_pipe[0];
+
+ return 0;
+ break;
+ }
+ g_assert_not_reached();
+ return -1;
+
+ bail_fork:
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ bail_stderr:
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ bail_stdout:
+ close(stdin_pipe[0]);
+ close(stdin_pipe[1]);
+ bail_stdin:
+ if(reapchild) {
+ close(pid_pipe[0]);
+ close(pid_pipe[1]);
+ }
+ bail_pid:
+ close(ready_a[0]);
+ close(ready_a[1]);
+ close(ready_b[0]);
+ close(ready_b[1]);
+ bail_ready:
+ *child = -1;
+ return -1;
+}
+
+/**
+ * pty_set_size:
+ * @master: the file descriptor of the pty master
+ * @columns: the desired number of columns
+ * @rows: the desired number of rows
+ *
+ * Attempts to resize the pseudo terminal's window size. If successful, the
+ * OS kernel will send #SIGWINCH to the child process group.
+ *
+ * Returns: 0 on success, -1 on failure.
+ */
+int
+_pty_set_size(int master, int columns, int rows)
+{
+ struct winsize size;
+ int ret;
+ memset(&size, 0, sizeof(size));
+ size.ws_row = rows ? rows : 24;
+ size.ws_col = columns ? columns : 80;
+ ret = ioctl(master, TIOCSWINSZ, &size);
+ return ret;
+}
+
+
+static char *
+_pty_ptsname(int master)
+{
+#if defined(HAVE_PTSNAME_R)
+ gsize len = 1024;
+ char *buf = NULL;
+ int i;
+ do {
+ buf = g_malloc0(len);
+ i = ptsname_r(master, buf, len - 1);
+ switch (i) {
+ case 0:
+ /* Return the allocated buffer with the name in it. */
+ return buf;
+ break;
+ default:
+ g_free(buf);
+ buf = NULL;
+ break;
+ }
+ len *= 2;
+ } while ((i != 0) && (errno == ERANGE));
+#elif defined(HAVE_PTSNAME)
+ char *p;
+ if ((p = ptsname(master)) != NULL) {
+ return g_strdup(p);
+ }
+#elif defined(TIOCGPTN)
+ int pty = 0;
+ if (ioctl(master, TIOCGPTN, &pty) == 0) {
+ return g_strdup_printf("/dev/pts/%d", pty);
+ }
+#endif
+ return NULL;
+}
+
+static int
+_pty_getpt(void)
+{
+ int fd, flags;
+#ifdef HAVE_GETPT
+ /* Call the system's function for allocating a pty. */
+ fd = getpt();
+#elif defined(HAVE_POSIX_OPENPT)
+ fd = posix_openpt(O_RDWR | O_NOCTTY);
+#else
+ /* Try to allocate a pty by accessing the pty master multiplex. */
+ fd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
+ if ((fd == -1) && (errno == ENOENT)) {
+ fd = open("/dev/ptc", O_RDWR | O_NOCTTY); /* AIX */
+ }
+#endif
+ /* Set it to blocking. */
+ flags = fcntl(fd, F_GETFL);
+ flags &= ~(O_NONBLOCK);
+ fcntl(fd, F_SETFL, flags);
+ return fd;
+}
+
+static int
+_pty_grantpt(int master)
+{
+#ifdef HAVE_GRANTPT
+ return grantpt(master);
+#else
+ return 0;
+#endif
+}
+
+static int
+_pty_unlockpt(int fd)
+{
+#ifdef HAVE_UNLOCKPT
+ return unlockpt(fd);
+#elif defined(TIOCSPTLCK)
+ int zero = 0;
+ return ioctl(fd, TIOCSPTLCK, &zero);
+#else
+ return -1;
+#endif
+}
+
+static int
+_pty_open_unix98(pid_t *child, guint flags, char **env_add,
+ const char *command, char **argv,
+ const char *directory, int columns, int rows,
+ int *stdin_fd, int *stdout_fd, int *stderr_fd)
+{
+ int fd;
+ char *buf;
+
+ /* Attempt to open the master. */
+ fd = _pty_getpt();
+ if (fd != -1) {
+ /* Read the slave number and unlock it. */
+ if (((buf = _pty_ptsname(fd)) == NULL) ||
+ (_pty_grantpt(fd) != 0) ||
+ (_pty_unlockpt(fd) != 0)) {
+ close(fd);
+ fd = -1;
+ } else {
+ /* Start up a child process with the given command. */
+ if (_pty_fork_on_pty_name(buf, fd, env_add, command,
+ argv, directory,
+ columns, rows,
+ stdin_fd, stdout_fd, stderr_fd,
+ child,
+ flags & PTY_REAP_CHILD,
+ flags & PTY_LOGIN_TTY) != 0) {
+ close(fd);
+ fd = -1;
+ }
+ g_free(buf);
+ }
+ }
+ return fd;
+}
+
+/**
+ * pty_open:
+ * @child: location to store the new process's ID
+ * @env_add: a list of environment variables to add to the child's environment
+ * @command: name of the binary to run
+ * @argv: arguments to pass to @command
+ * @directory: directory to start the new command in, or NULL
+ * @columns: desired window columns
+ * @rows: desired window rows
+ * @lastlog: TRUE if the lastlog should be updated
+ * @utmp: TRUE if the utmp or utmpx log should be updated
+ * @wtmp: TRUE if the wtmp or wtmpx log should be updated
+ *
+ * Starts a new copy of @command running under a psuedo-terminal, optionally in
+ * the supplied @directory, with window size set to @rows x @columns
+ * and variables in @env_add added to its environment. If any combination of
+ * @lastlog, @utmp, and @wtmp is set, then the session is logged in the
+ * corresponding system files.
+ *
+ * Returns: an open file descriptor for the pty master, -1 on failure
+ */
+int
+pty_open(pid_t *child, guint flags, char **env_add,
+ const char *command, char **argv, const char *directory,
+ int columns, int rows,
+ int *stdin_fd, int *stdout_fd, int *stderr_fd)
+{
+ int ret = -1;
+ if (ret == -1) {
+ ret = _pty_open_unix98(child, flags, env_add, command,
+ argv, directory, columns, rows,
+ stdin_fd, stdout_fd, stderr_fd);
+ }
+ return ret;
+}
+
+
+#ifdef PTY_MAIN
+int fd;
+
+static void
+sigchld_handler(int signum)
+{
+}
+
+int
+main(int argc, char **argv)
+{
+ pid_t child = 0;
+ char c;
+ int ret;
+ signal(SIGCHLD, sigchld_handler);
+ fd = pty_open(&child, 0, NULL,
+ (argc > 1) ? argv[1] : NULL,
+ (argc > 1) ? argv + 1 : NULL,
+ NULL,
+ 0, 0,
+ NULL, NULL, NULL);
+ if (child == 0) {
+ int i;
+ for (i = 0; ; i++) {
+ switch (i % 3) {
+ case 0:
+ case 1:
+ fprintf(stdout, "%d\n", i);
+ break;
+ case 2:
+ fprintf(stderr, "%d\n", i);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ sleep(1);
+ }
+ }
+ g_print("Child pid is %d.\n", (int)child);
+ do {
+ ret = n_read(fd, &c, 1);
+ if (ret == 0) {
+ break;
+ }
+ if ((ret == -1) && (errno != EAGAIN) && (errno != EINTR)) {
+ break;
+ }
+ if (argc < 2) {
+ n_write(STDOUT_FILENO, "[", 1);
+ }
+ n_write(STDOUT_FILENO, &c, 1);
+ if (argc < 2) {
+ n_write(STDOUT_FILENO, "]", 1);
+ }
+ } while (TRUE);
+ return 0;
+}
+#endif
diff --git a/trunk/daemon/pty_open.h b/trunk/daemon/pty_open.h
new file mode 100644
index 00000000..c9bc0862
--- /dev/null
+++ b/trunk/daemon/pty_open.h
@@ -0,0 +1,65 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/*
+ * Copyright (C) 2001,2002,2004 Red Hat, Inc.
+ *
+ * This 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 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 Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PTY_OPEN_H
+#define PTY_OPEN_H
+
+#include <sys/types.h>
+
+G_BEGIN_DECLS
+
+enum {
+ PTY_REAP_CHILD = 1,
+ PTY_LOGIN_TTY = 2
+};
+
+/* Start up the given binary (exact path, not interpreted at all) in a
+ * pseudo-terminal of its own, returning the descriptor for the master
+ * side of the PTY pair, logging the session to the specified files, and
+ * storing the child's PID in the given argument. */
+int pty_open(pid_t *child, guint flags, char **env_add,
+ const char *command, char **argv, const char *directory,
+ int columns, int rows,
+ int *stdin_fd, int *stdout_fd, int *stderr_fd);
+int pty_get_size(int master, int *columns, int *rows);
+
+G_END_DECLS
+
+#endif
diff --git a/trunk/daemon/sftp.h b/trunk/daemon/sftp.h
new file mode 100644
index 00000000..95edf8c7
--- /dev/null
+++ b/trunk/daemon/sftp.h
@@ -0,0 +1,87 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+/* From draft-ietf-secsh-filexfer-02.txt */
+
+/* version */
+#define SSH_FILEXFER_VERSION 3
+
+/* client to server */
+#define SSH_FXP_INIT 1
+#define SSH_FXP_OPEN 3
+#define SSH_FXP_CLOSE 4
+#define SSH_FXP_READ 5
+#define SSH_FXP_WRITE 6
+#define SSH_FXP_LSTAT 7
+#define SSH_FXP_STAT_VERSION_0 7
+#define SSH_FXP_FSTAT 8
+#define SSH_FXP_SETSTAT 9
+#define SSH_FXP_FSETSTAT 10
+#define SSH_FXP_OPENDIR 11
+#define SSH_FXP_READDIR 12
+#define SSH_FXP_REMOVE 13
+#define SSH_FXP_MKDIR 14
+#define SSH_FXP_RMDIR 15
+#define SSH_FXP_REALPATH 16
+#define SSH_FXP_STAT 17
+#define SSH_FXP_RENAME 18
+#define SSH_FXP_READLINK 19
+#define SSH_FXP_SYMLINK 20
+
+/* server to client */
+#define SSH_FXP_VERSION 2
+#define SSH_FXP_STATUS 101
+#define SSH_FXP_HANDLE 102
+#define SSH_FXP_DATA 103
+#define SSH_FXP_NAME 104
+#define SSH_FXP_ATTRS 105
+
+#define SSH_FXP_EXTENDED 200
+#define SSH_FXP_EXTENDED_REPLY 201
+
+/* attributes */
+#define SSH_FILEXFER_ATTR_SIZE 0x00000001
+#define SSH_FILEXFER_ATTR_UIDGID 0x00000002
+#define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
+#define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
+#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
+
+/* portable open modes */
+#define SSH_FXF_READ 0x00000001
+#define SSH_FXF_WRITE 0x00000002
+#define SSH_FXF_APPEND 0x00000004
+#define SSH_FXF_CREAT 0x00000008
+#define SSH_FXF_TRUNC 0x00000010
+#define SSH_FXF_EXCL 0x00000020
+
+/* status messages */
+#define SSH_FX_OK 0
+#define SSH_FX_EOF 1
+#define SSH_FX_NO_SUCH_FILE 2
+#define SSH_FX_PERMISSION_DENIED 3
+#define SSH_FX_FAILURE 4
+#define SSH_FX_BAD_MESSAGE 5
+#define SSH_FX_NO_CONNECTION 6
+#define SSH_FX_CONNECTION_LOST 7
+#define SSH_FX_OP_UNSUPPORTED 8
+#define SSH_FX_MAX 8
+
diff --git a/trunk/daemon/sftp.mount.in b/trunk/daemon/sftp.mount.in
new file mode 100644
index 00000000..85257535
--- /dev/null
+++ b/trunk/daemon/sftp.mount.in
@@ -0,0 +1,8 @@
+[Mount]
+Type=sftp
+Exec=@libexecdir@/gvfsd-sftp
+AutoMount=false
+Scheme=sftp
+SchemeAliases=ssh
+DefaultPort=22
+HostnameIsInetAddress=true
diff --git a/trunk/daemon/smb-browse.mount.in b/trunk/daemon/smb-browse.mount.in
new file mode 100644
index 00000000..e3b267f9
--- /dev/null
+++ b/trunk/daemon/smb-browse.mount.in
@@ -0,0 +1,6 @@
+[Mount]
+Type=smb-network;smb-server
+Exec=@libexecdir@/gvfsd-smb-browse
+DBusName=org.gtk.vfs.mountpoint.smb_browse
+AutoMount=false
+Scheme=smb
diff --git a/trunk/daemon/smb.mount.in b/trunk/daemon/smb.mount.in
new file mode 100644
index 00000000..7612af2a
--- /dev/null
+++ b/trunk/daemon/smb.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=smb-share
+Exec=@libexecdir@/gvfsd-smb
+AutoMount=false
+Scheme=smb
diff --git a/trunk/daemon/soup-input-stream.c b/trunk/daemon/soup-input-stream.c
new file mode 100644
index 00000000..ce3fa939
--- /dev/null
+++ b/trunk/daemon/soup-input-stream.c
@@ -0,0 +1,921 @@
+/* soup-input-stream.c, based on gsocketinputstream.c
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libsoup/soup.h>
+
+#include "soup-input-stream.h"
+
+static void soup_input_stream_seekable_iface_init (GSeekableIface *seekable_iface);
+
+G_DEFINE_TYPE_WITH_CODE (SoupInputStream, soup_input_stream, G_TYPE_INPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
+ soup_input_stream_seekable_iface_init))
+
+typedef void (*SoupInputStreamCallback) (GInputStream *);
+
+typedef struct {
+ SoupSession *session;
+ GMainContext *async_context;
+ SoupMessage *msg;
+ gboolean got_headers, finished;
+ goffset offset;
+
+ GCancellable *cancellable;
+ GSource *cancel_watch;
+ SoupInputStreamCallback got_headers_cb;
+ SoupInputStreamCallback got_chunk_cb;
+ SoupInputStreamCallback finished_cb;
+ SoupInputStreamCallback cancelled_cb;
+
+ guchar *leftover_buffer;
+ gsize leftover_bufsize, leftover_offset;
+
+ guchar *caller_buffer;
+ gsize caller_bufsize, caller_nread;
+ GAsyncReadyCallback outstanding_callback;
+ GSimpleAsyncResult *result;
+
+} SoupInputStreamPrivate;
+#define SOUP_INPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_INPUT_STREAM, SoupInputStreamPrivate))
+
+
+static gssize soup_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean soup_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static void soup_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize soup_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void soup_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean soup_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+static goffset soup_input_stream_tell (GSeekable *seekable);
+
+static gboolean soup_input_stream_can_seek (GSeekable *seekable);
+static gboolean soup_input_stream_seek (GSeekable *seekable,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error);
+
+static gboolean soup_input_stream_can_truncate (GSeekable *seekable);
+static gboolean soup_input_stream_truncate (GSeekable *seekable,
+ goffset offset,
+ GCancellable *cancellable,
+ GError **error);
+
+static void soup_input_stream_got_headers (SoupMessage *msg, gpointer stream);
+static void soup_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer stream);
+static void soup_input_stream_finished (SoupMessage *msg, gpointer stream);
+
+static void
+soup_input_stream_finalize (GObject *object)
+{
+ SoupInputStream *stream = SOUP_INPUT_STREAM (object);
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ g_object_unref (priv->session);
+
+ g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_got_headers), stream);
+ g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_got_chunk), stream);
+ g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_input_stream_finished), stream);
+ g_object_unref (priv->msg);
+ g_free (priv->leftover_buffer);
+
+ if (G_OBJECT_CLASS (soup_input_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (soup_input_stream_parent_class)->finalize) (object);
+}
+
+static void
+soup_input_stream_class_init (SoupInputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (SoupInputStreamPrivate));
+
+ gobject_class->finalize = soup_input_stream_finalize;
+
+ stream_class->read_fn = soup_input_stream_read;
+ stream_class->close_fn = soup_input_stream_close;
+ stream_class->read_async = soup_input_stream_read_async;
+ stream_class->read_finish = soup_input_stream_read_finish;
+ stream_class->close_async = soup_input_stream_close_async;
+ stream_class->close_finish = soup_input_stream_close_finish;
+}
+
+static void
+soup_input_stream_seekable_iface_init (GSeekableIface *seekable_iface)
+{
+ seekable_iface->tell = soup_input_stream_tell;
+ seekable_iface->can_seek = soup_input_stream_can_seek;
+ seekable_iface->seek = soup_input_stream_seek;
+ seekable_iface->can_truncate = soup_input_stream_can_truncate;
+ seekable_iface->truncate_fn = soup_input_stream_truncate;
+}
+
+static void
+soup_input_stream_init (SoupInputStream *stream)
+{
+ ;
+}
+
+static void
+soup_input_stream_queue_message (SoupInputStream *stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->got_headers = priv->finished = FALSE;
+
+ /* Add an extra ref since soup_session_queue_message steals one */
+ g_object_ref (priv->msg);
+ soup_session_queue_message (priv->session, priv->msg, NULL, NULL);
+}
+
+/**
+ * soup_input_stream_new:
+ * @session: the #SoupSession to use
+ * @msg: the #SoupMessage whose response will be streamed
+ *
+ * Prepares to send @msg over @session, and returns a #GInputStream
+ * that can be used to read the response.
+ *
+ * @msg may not be sent until the first read call; if you need to look
+ * at the status code or response headers before reading the body, you
+ * can use soup_input_stream_send() or soup_input_stream_send_async()
+ * to force the message to be sent and the response headers read.
+ *
+ * If @msg gets a non-2xx result, the first read (or send) will return
+ * an error with type %SOUP_INPUT_STREAM_HTTP_ERROR.
+ *
+ * Internally, #SoupInputStream is implemented using asynchronous I/O,
+ * so if you are using the synchronous API (eg,
+ * g_input_stream_read()), you should create a new #GMainContext and
+ * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
+ * you don't, then synchronous #GInputStream calls will cause the main
+ * loop to be run recursively.) The async #GInputStream API works fine
+ * with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
+ *
+ * Returns: a new #GInputStream.
+ **/
+GInputStream *
+soup_input_stream_new (SoupSession *session, SoupMessage *msg)
+{
+ SoupInputStream *stream;
+ SoupInputStreamPrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
+
+ stream = g_object_new (SOUP_TYPE_INPUT_STREAM, NULL);
+ priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->session = g_object_ref (session);
+ priv->async_context = soup_session_get_async_context (session);
+ priv->msg = g_object_ref (msg);
+
+ g_signal_connect (msg, "got_headers",
+ G_CALLBACK (soup_input_stream_got_headers), stream);
+ g_signal_connect (msg, "got_chunk",
+ G_CALLBACK (soup_input_stream_got_chunk), stream);
+ g_signal_connect (msg, "finished",
+ G_CALLBACK (soup_input_stream_finished), stream);
+
+ soup_input_stream_queue_message (stream);
+ return G_INPUT_STREAM (stream);
+}
+
+static void
+soup_input_stream_got_headers (SoupMessage *msg, gpointer stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ /* If the status is unsuccessful, we just ignore the signal and let
+ * libsoup keep going (eventually either it will requeue the request
+ * (after handling authentication/redirection), or else the
+ * "finished" handler will run).
+ */
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ return;
+
+ priv->got_headers = TRUE;
+ if (!priv->caller_buffer)
+ {
+ /* Not ready to read the body yet */
+ soup_session_pause_message (priv->session, msg);
+ }
+
+ if (priv->got_headers_cb)
+ priv->got_headers_cb (stream);
+}
+
+static void
+soup_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer,
+ gpointer stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+ const gchar *chunk = chunk_buffer->data;
+ gsize chunk_size = chunk_buffer->length;
+
+ /* We only pay attention to the chunk if it's part of a successful
+ * response.
+ */
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ return;
+
+ /* Sanity check */
+ if (priv->caller_bufsize == 0 || priv->leftover_bufsize != 0)
+ g_warning ("soup_input_stream_got_chunk called again before previous chunk was processed");
+
+ /* Copy what we can into priv->caller_buffer */
+ if (priv->caller_bufsize - priv->caller_nread > 0)
+ {
+ gsize nread = MIN (chunk_size, priv->caller_bufsize - priv->caller_nread);
+
+ memcpy (priv->caller_buffer + priv->caller_nread, chunk, nread);
+ priv->caller_nread += nread;
+ priv->offset += nread;
+ chunk += nread;
+ chunk_size -= nread;
+ }
+
+ if (chunk_size > 0)
+ {
+ /* Copy the rest into priv->leftover_buffer. If there's already
+ * some data there, realloc and append. Otherwise just copy.
+ */
+ if (priv->leftover_bufsize)
+ {
+ priv->leftover_buffer = g_realloc (priv->leftover_buffer,
+ priv->leftover_bufsize + chunk_size);
+ memcpy (priv->leftover_buffer + priv->leftover_bufsize,
+ chunk, chunk_size);
+ priv->leftover_bufsize += chunk_size;
+ }
+ else
+ {
+ priv->leftover_bufsize = chunk_size;
+ priv->leftover_buffer = g_memdup (chunk, chunk_size);
+ priv->leftover_offset = 0;
+ }
+ }
+
+ soup_session_pause_message (priv->session, msg);
+ if (priv->got_chunk_cb)
+ priv->got_chunk_cb (stream);
+}
+
+static void
+soup_input_stream_finished (SoupMessage *msg, gpointer stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->finished = TRUE;
+
+ if (priv->finished_cb)
+ priv->finished_cb (stream);
+}
+
+static gboolean
+soup_input_stream_cancelled (GIOChannel *chan, GIOCondition condition,
+ gpointer stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->cancel_watch = NULL;
+
+ soup_session_pause_message (priv->session, priv->msg);
+ if (priv->cancelled_cb)
+ priv->cancelled_cb (stream);
+
+ return FALSE;
+}
+
+static void
+soup_input_stream_prepare_for_io (GInputStream *stream,
+ GCancellable *cancellable,
+ guchar *buffer,
+ gsize count)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+ int cancel_fd;
+
+ priv->cancellable = cancellable;
+ cancel_fd = g_cancellable_get_fd (cancellable);
+ if (cancel_fd != -1)
+ {
+ GIOChannel *chan = g_io_channel_unix_new (cancel_fd);
+ priv->cancel_watch = soup_add_io_watch (priv->async_context, chan,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ soup_input_stream_cancelled,
+ stream);
+ g_io_channel_unref (chan);
+ }
+
+ priv->caller_buffer = buffer;
+ priv->caller_bufsize = count;
+ priv->caller_nread = 0;
+
+ if (priv->got_headers)
+ soup_session_unpause_message (priv->session, priv->msg);
+}
+
+static void
+soup_input_stream_done_io (GInputStream *stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ if (priv->cancel_watch)
+ {
+ g_source_destroy (priv->cancel_watch);
+ priv->cancel_watch = NULL;
+ }
+ priv->cancellable = NULL;
+
+ priv->caller_buffer = NULL;
+ priv->caller_bufsize = 0;
+}
+
+static gboolean
+set_error_if_http_failed (SoupMessage *msg, GError **error)
+{
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ g_set_error_literal (error, SOUP_HTTP_ERROR,
+ msg->status_code, msg->reason_phrase);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gsize
+read_from_leftover (SoupInputStreamPrivate *priv,
+ gpointer buffer, gsize bufsize)
+{
+ gsize nread;
+
+ if (priv->leftover_bufsize - priv->leftover_offset <= bufsize)
+ {
+ nread = priv->leftover_bufsize - priv->leftover_offset;
+ memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
+
+ g_free (priv->leftover_buffer);
+ priv->leftover_buffer = NULL;
+ priv->leftover_bufsize = priv->leftover_offset = 0;
+ }
+ else
+ {
+ nread = bufsize;
+ memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
+ priv->leftover_offset += nread;
+ }
+
+ priv->offset += nread;
+ return nread;
+}
+
+/* This does the work of soup_input_stream_send(), assuming that the
+ * GInputStream pending flag has already been set. It is also used by
+ * soup_input_stream_send_async() in some circumstances.
+ */
+static gboolean
+soup_input_stream_send_internal (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ soup_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
+ while (!priv->finished && !priv->got_headers &&
+ !g_cancellable_is_cancelled (cancellable))
+ g_main_context_iteration (priv->async_context, TRUE);
+ soup_input_stream_done_io (stream);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+ else if (set_error_if_http_failed (priv->msg, error))
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * soup_input_stream_send:
+ * @stream: a #SoupInputStream
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: location to store the error occuring, or %NULL to ignore
+ *
+ * Synchronously sends the HTTP request associated with @stream, and
+ * reads the response headers. Call this after soup_input_stream_new()
+ * and before the first g_input_stream_read() if you want to check the
+ * HTTP status code before you start reading.
+ *
+ * Return value: %TRUE if msg has a successful (2xx) status, %FALSE if
+ * not.
+ **/
+gboolean
+soup_input_stream_send (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (SOUP_IS_INPUT_STREAM (stream), FALSE);
+
+ if (!g_input_stream_set_pending (stream, error))
+ return FALSE;
+ result = soup_input_stream_send_internal (stream, cancellable, error);
+ g_input_stream_clear_pending (stream);
+
+ return result;
+}
+
+static gssize
+soup_input_stream_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ if (priv->finished)
+ return 0;
+
+ /* If there is data leftover from a previous read, return it. */
+ if (priv->leftover_bufsize)
+ return read_from_leftover (priv, buffer, count);
+
+ /* No leftover data, accept one chunk from the network */
+ soup_input_stream_prepare_for_io (stream, cancellable, buffer, count);
+ while (!priv->finished && priv->caller_nread == 0 &&
+ !g_cancellable_is_cancelled (cancellable))
+ g_main_context_iteration (priv->async_context, TRUE);
+ soup_input_stream_done_io (stream);
+
+ if (priv->caller_nread > 0)
+ return priv->caller_nread;
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+ else if (set_error_if_http_failed (priv->msg, error))
+ return -1;
+ else
+ return 0;
+}
+
+static gboolean
+soup_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ if (!priv->finished)
+ soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
+
+ return TRUE;
+}
+
+static void
+wrapper_callback (GObject *source_object, GAsyncResult *res,
+ gpointer user_data)
+{
+ GInputStream *stream = G_INPUT_STREAM (source_object);
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ g_input_stream_clear_pending (stream);
+ if (priv->outstanding_callback)
+ (*priv->outstanding_callback) (source_object, res, user_data);
+ priv->outstanding_callback = NULL;
+ g_object_unref (stream);
+}
+
+static void
+send_async_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GError *error = NULL;
+ gboolean success;
+
+ success = soup_input_stream_send_internal (G_INPUT_STREAM (object),
+ cancellable, &error);
+ g_simple_async_result_set_op_res_gboolean (res, success);
+ if (error)
+ {
+ g_simple_async_result_set_from_error (res, error);
+ g_error_free (error);
+ }
+}
+
+static void
+soup_input_stream_send_async_in_thread (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
+ soup_input_stream_send_async_in_thread);
+ g_simple_async_result_run_in_thread (res, send_async_thread,
+ io_priority, cancellable);
+ g_object_unref (res);
+}
+
+static void
+send_async_finished (GInputStream *stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+ GError *error = NULL;
+
+ if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error))
+ set_error_if_http_failed (priv->msg, &error);
+
+ priv->got_headers_cb = NULL;
+ priv->finished_cb = NULL;
+ soup_input_stream_done_io (stream);
+
+ result = priv->result;
+ priv->result = NULL;
+
+ g_simple_async_result_set_op_res_gboolean (result, error == NULL);
+ if (error)
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+ g_simple_async_result_complete (result);
+}
+
+static void
+soup_input_stream_send_async_internal (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+
+ g_object_ref (stream);
+ priv->outstanding_callback = callback;
+
+ /* If the session uses the default GMainContext, then we can do
+ * async I/O directly. But if it has its own main context, it's
+ * easier to just run it in another thread.
+ */
+ if (soup_session_get_async_context (priv->session))
+ {
+ soup_input_stream_send_async_in_thread (stream, io_priority, cancellable,
+ wrapper_callback, user_data);
+ return;
+ }
+
+ priv->got_headers_cb = send_async_finished;
+ priv->finished_cb = send_async_finished;
+
+ soup_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
+ priv->result = g_simple_async_result_new (G_OBJECT (stream),
+ wrapper_callback, user_data,
+ soup_input_stream_send_async);
+}
+
+/**
+ * soup_input_stream_send_async:
+ * @stream: a #SoupInputStream
+ * @io_priority: the io priority of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: callback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously sends the HTTP request associated with @stream, and
+ * reads the response headers. Call this after soup_input_stream_new()
+ * and before the first g_input_stream_read_async() if you want to
+ * check the HTTP status code before you start reading.
+ **/
+void
+soup_input_stream_send_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (SOUP_IS_INPUT_STREAM (stream));
+
+ if (!g_input_stream_set_pending (stream, &error))
+ {
+ g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
+ callback,
+ user_data,
+ error);
+ g_error_free (error);
+ return;
+ }
+ soup_input_stream_send_async_internal (stream, io_priority, cancellable,
+ callback, user_data);
+}
+
+/**
+ * soup_input_stream_send_finish:
+ * @stream: a #SoupInputStream
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occuring, or %NULL to
+ * ignore.
+ *
+ * Finishes a soup_input_stream_send_async() operation.
+ *
+ * Return value: %TRUE if the message was sent successfully and
+ * received a successful status code, %FALSE if not.
+ **/
+gboolean
+soup_input_stream_send_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == soup_input_stream_send_async, FALSE);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
+read_async_done (GInputStream *stream)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+ GError *error = NULL;
+
+ result = priv->result;
+ priv->result = NULL;
+
+ if (g_cancellable_set_error_if_cancelled (priv->cancellable, &error) ||
+ set_error_if_http_failed (priv->msg, &error))
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+ else
+ g_simple_async_result_set_op_res_gssize (result, priv->caller_nread);
+
+ priv->got_chunk_cb = NULL;
+ priv->finished_cb = NULL;
+ priv->cancelled_cb = NULL;
+ soup_input_stream_done_io (stream);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+static void
+soup_input_stream_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+
+ /* If the session uses the default GMainContext, then we can do
+ * async I/O directly. But if it has its own main context, we fall
+ * back to the async-via-sync-in-another-thread implementation.
+ */
+ if (soup_session_get_async_context (priv->session))
+ {
+ G_INPUT_STREAM_CLASS (soup_input_stream_parent_class)->
+ read_async (stream, buffer, count, io_priority,
+ cancellable, callback, user_data);
+ return;
+ }
+
+ result = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ soup_input_stream_read_async);
+
+ if (priv->finished)
+ {
+ g_simple_async_result_set_op_res_gssize (result, 0);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ if (priv->leftover_bufsize)
+ {
+ gsize nread = read_from_leftover (priv, buffer, count);
+ g_simple_async_result_set_op_res_gssize (result, nread);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ priv->result = result;
+
+ priv->got_chunk_cb = read_async_done;
+ priv->finished_cb = read_async_done;
+ priv->cancelled_cb = read_async_done;
+ soup_input_stream_prepare_for_io (stream, cancellable, buffer, count);
+}
+
+static gssize
+soup_input_stream_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), -1);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == soup_input_stream_read_async, -1);
+
+ return g_simple_async_result_get_op_res_gssize (simple);
+}
+
+static void
+soup_input_stream_close_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ gboolean success;
+ GError *error = NULL;
+
+ result = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ soup_input_stream_close_async);
+ success = soup_input_stream_close (stream, cancellable, &error);
+ g_simple_async_result_set_op_res_gboolean (result, success);
+ if (error)
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+}
+
+static gboolean
+soup_input_stream_close_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
+
+static goffset
+soup_input_stream_tell (GSeekable *seekable)
+{
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (seekable);
+
+ return priv->offset;
+}
+
+static gboolean
+soup_input_stream_can_seek (GSeekable *seekable)
+{
+ return TRUE;
+}
+
+extern void soup_message_io_cleanup (SoupMessage *msg);
+
+static gboolean
+soup_input_stream_seek (GSeekable *seekable,
+ goffset offset,
+ GSeekType type,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInputStream *stream = G_INPUT_STREAM (seekable);
+ SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (seekable);
+ char *range;
+
+ if (type == G_SEEK_END)
+ {
+ /* FIXME: we could send "bytes=-offset", but unless we know the
+ * Content-Length, we wouldn't be able to answer a tell() properly.
+ * We could find the Content-Length by doing a HEAD...
+ */
+
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "G_SEEK_END not currently supported");
+ return FALSE;
+ }
+
+ if (!g_input_stream_set_pending (stream, error))
+ return FALSE;
+
+ soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
+ soup_message_io_cleanup (priv->msg);
+
+ switch (type)
+ {
+ case G_SEEK_CUR:
+ offset += priv->offset;
+ /* fall through */
+
+ case G_SEEK_SET:
+ range = g_strdup_printf ("bytes=%"G_GUINT64_FORMAT"-", (guint64)offset);
+ priv->offset = offset;
+ break;
+
+ case G_SEEK_END:
+ range = NULL; /* keep compilers happy */
+ g_return_val_if_reached (FALSE);
+ break;
+
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+
+ soup_message_headers_remove (priv->msg->request_headers, "Range");
+ soup_message_headers_append (priv->msg->request_headers, "Range", range);
+ g_free (range);
+
+ soup_input_stream_queue_message (SOUP_INPUT_STREAM (stream));
+
+ g_input_stream_clear_pending (stream);
+ return TRUE;
+}
+
+static gboolean
+soup_input_stream_can_truncate (GSeekable *seekable)
+{
+ return FALSE;
+}
+
+static gboolean
+soup_input_stream_truncate (GSeekable *seekable,
+ goffset offset,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Truncate not allowed on input stream");
+ return FALSE;
+}
+
+GQuark
+soup_http_error_quark (void)
+{
+ static GQuark error;
+ if (!error)
+ error = g_quark_from_static_string ("soup_http_error_quark");
+ return error;
+}
diff --git a/trunk/daemon/soup-input-stream.h b/trunk/daemon/soup-input-stream.h
new file mode 100644
index 00000000..dd2c5402
--- /dev/null
+++ b/trunk/daemon/soup-input-stream.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SOUP_INPUT_STREAM_H__
+#define __SOUP_INPUT_STREAM_H__
+
+#include <gio/gio.h>
+#include <libsoup/soup-types.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_INPUT_STREAM (soup_input_stream_get_type ())
+#define SOUP_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_INPUT_STREAM, SoupInputStream))
+#define SOUP_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SOUP_TYPE_INPUT_STREAM, SoupInputStreamClass))
+#define SOUP_IS_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_INPUT_STREAM))
+#define SOUP_IS_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_INPUT_STREAM))
+#define SOUP_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_INPUT_STREAM, SoupInputStreamClass))
+
+typedef struct SoupInputStream SoupInputStream;
+typedef struct SoupInputStreamClass SoupInputStreamClass;
+
+struct SoupInputStream
+{
+ GInputStream parent;
+
+};
+
+struct SoupInputStreamClass
+{
+ GInputStreamClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+};
+
+GType soup_input_stream_get_type (void) G_GNUC_CONST;
+
+GInputStream *soup_input_stream_new (SoupSession *session,
+ SoupMessage *msg);
+
+gboolean soup_input_stream_send (GInputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+
+void soup_input_stream_send_async (GInputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean soup_input_stream_send_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+#define SOUP_HTTP_ERROR soup_http_error_quark()
+GQuark soup_http_error_quark (void);
+
+G_END_DECLS
+
+#endif /* __SOUP_INPUT_STREAM_H__ */
diff --git a/trunk/daemon/soup-output-stream.c b/trunk/daemon/soup-output-stream.c
new file mode 100644
index 00000000..86ff8a43
--- /dev/null
+++ b/trunk/daemon/soup-output-stream.c
@@ -0,0 +1,417 @@
+/* soup-output-stream.c, based on gunixoutputstream.c
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libsoup/soup.h>
+
+#include "soup-output-stream.h"
+#include "soup-input-stream.h"
+
+G_DEFINE_TYPE (SoupOutputStream, soup_output_stream, G_TYPE_OUTPUT_STREAM)
+
+typedef void (*SoupOutputStreamCallback) (GOutputStream *);
+
+typedef struct {
+ SoupSession *session;
+ GMainContext *async_context;
+ SoupMessage *msg;
+ gboolean finished;
+
+ goffset size, offset;
+ GByteArray *ba;
+
+ GCancellable *cancellable;
+ GSource *cancel_watch;
+ SoupOutputStreamCallback finished_cb;
+ SoupOutputStreamCallback cancelled_cb;
+
+ GSimpleAsyncResult *result;
+} SoupOutputStreamPrivate;
+#define SOUP_OUTPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_OUTPUT_STREAM, SoupOutputStreamPrivate))
+
+static gssize soup_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean soup_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static void soup_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gssize soup_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+static void soup_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data);
+static gboolean soup_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error);
+
+static void soup_output_stream_finished (SoupMessage *msg, gpointer stream);
+
+static void
+soup_output_stream_finalize (GObject *object)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (object);
+
+ g_object_unref (priv->session);
+
+ g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_output_stream_finished), object);
+ g_object_unref (priv->msg);
+
+ if (priv->ba)
+ g_byte_array_free (priv->ba, TRUE);
+
+ if (G_OBJECT_CLASS (soup_output_stream_parent_class)->finalize)
+ (*G_OBJECT_CLASS (soup_output_stream_parent_class)->finalize) (object);
+}
+
+static void
+soup_output_stream_class_init (SoupOutputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (SoupOutputStreamPrivate));
+
+ gobject_class->finalize = soup_output_stream_finalize;
+
+ stream_class->write_fn = soup_output_stream_write;
+ stream_class->close_fn = soup_output_stream_close;
+ stream_class->write_async = soup_output_stream_write_async;
+ stream_class->write_finish = soup_output_stream_write_finish;
+ stream_class->close_async = soup_output_stream_close_async;
+ stream_class->close_finish = soup_output_stream_close_finish;
+}
+
+static void
+soup_output_stream_init (SoupOutputStream *stream)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->ba = g_byte_array_new ();
+}
+
+
+/**
+ * soup_output_stream_new:
+ * @session: the #SoupSession to use
+ * @msg: the #SoupMessage whose request will be streamed
+ * @size: the total size of the request body, or -1 if not known
+ *
+ * Prepares to send @msg over @session, and returns a #GOutputStream
+ * that can be used to write the response. The server's response will
+ * be available in @msg after calling soup_output_stream_close()
+ * (which will return a %SOUP_OUTPUT_STREAM_HTTP_ERROR #GError if the
+ * status is not 2xx).
+ *
+ * If you know the total number of bytes that will be written, pass
+ * that in @size. Otherwise, pass -1. (If you pass a size, you MUST
+ * write that many bytes to the stream; Trying to write more than
+ * that, or closing the stream without having written enough, will
+ * result in an error.
+ *
+ * In some situations, the request will not actually be sent until you
+ * call g_output_stream_close(). (In fact, currently this is *always*
+ * true.)
+ *
+ * Internally, #SoupOutputStream is implemented using asynchronous
+ * I/O, so if you are using the synchronous API (eg,
+ * g_output_stream_write()), you should create a new #GMainContext and
+ * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
+ * you don't, then synchronous #GOutputStream calls will cause the
+ * main loop to be run recursively.) The async #GOutputStream API
+ * works fine with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
+ *
+ * Returns: a new #GOutputStream.
+ **/
+GOutputStream *
+soup_output_stream_new (SoupSession *session, SoupMessage *msg, goffset size)
+{
+ SoupOutputStream *stream;
+ SoupOutputStreamPrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
+
+ stream = g_object_new (SOUP_TYPE_OUTPUT_STREAM, NULL);
+ priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->session = g_object_ref (session);
+ priv->async_context = soup_session_get_async_context (session);
+ priv->msg = g_object_ref (msg);
+ priv->size = size;
+
+ return G_OUTPUT_STREAM (stream);
+}
+
+static gboolean
+soup_output_stream_cancelled (GIOChannel *chan, GIOCondition condition,
+ gpointer stream)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->cancel_watch = NULL;
+
+ soup_session_pause_message (priv->session, priv->msg);
+ if (priv->cancelled_cb)
+ priv->cancelled_cb (stream);
+
+ return FALSE;
+}
+
+static void
+soup_output_stream_prepare_for_io (GOutputStream *stream, GCancellable *cancellable)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+ int cancel_fd;
+
+ /* Move the buffer to the SoupMessage */
+ soup_message_body_append (priv->msg->request_body, SOUP_MEMORY_TAKE,
+ priv->ba->data, priv->ba->len);
+ g_byte_array_free (priv->ba, FALSE);
+ priv->ba = NULL;
+
+ /* Set up cancellation */
+ priv->cancellable = cancellable;
+ cancel_fd = g_cancellable_get_fd (cancellable);
+ if (cancel_fd != -1)
+ {
+ GIOChannel *chan = g_io_channel_unix_new (cancel_fd);
+ priv->cancel_watch = soup_add_io_watch (priv->async_context, chan,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ soup_output_stream_cancelled,
+ stream);
+ g_io_channel_unref (chan);
+ }
+
+ /* Add an extra ref since soup_session_queue_message steals one */
+ g_object_ref (priv->msg);
+ soup_session_queue_message (priv->session, priv->msg, NULL, NULL);
+}
+
+static void
+soup_output_stream_done_io (GOutputStream *stream)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ if (priv->cancel_watch)
+ {
+ g_source_destroy (priv->cancel_watch);
+ priv->cancel_watch = NULL;
+ }
+ priv->cancellable = NULL;
+}
+
+static gboolean
+set_error_if_http_failed (SoupMessage *msg, GError **error)
+{
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+ {
+ g_set_error_literal (error, SOUP_HTTP_ERROR,
+ msg->status_code, msg->reason_phrase);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gssize
+soup_output_stream_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ if (priv->size > 0 && priv->offset + count > priv->size) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ "Write would exceed caller-defined file size");
+ return -1;
+ }
+
+ g_byte_array_append (priv->ba, buffer, count);
+ priv->offset += count;
+ return count;
+}
+
+static int
+soup_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ if (priv->size > 0 && priv->offset != priv->size) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ "File is incomplete");
+ return -1;
+ }
+
+ soup_output_stream_prepare_for_io (stream, cancellable);
+ while (!priv->finished && !g_cancellable_is_cancelled (cancellable))
+ g_main_context_iteration (priv->async_context, TRUE);
+ soup_output_stream_done_io (stream);
+
+ return !set_error_if_http_failed (priv->msg, error);
+}
+
+static void
+soup_output_stream_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ soup_output_stream_write_async);
+
+ if (priv->size > 0 && priv->offset + count > priv->size)
+ {
+ GError *error;
+
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ "Write would exceed caller-defined file size");
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+ else
+ {
+ g_byte_array_append (priv->ba, buffer, count);
+ priv->offset += count;
+ g_simple_async_result_set_op_res_gssize (result, count);
+ }
+
+ g_simple_async_result_complete_in_idle (result);
+}
+
+static gssize
+soup_output_stream_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gssize nwritten;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == soup_output_stream_write_async);
+
+ nwritten = g_simple_async_result_get_op_res_gssize (simple);
+ return nwritten;
+}
+
+static void
+close_async_done (GOutputStream *stream)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+ GError *error = NULL;
+
+ result = priv->result;
+ priv->result = NULL;
+
+ if (g_cancellable_set_error_if_cancelled (priv->cancellable, &error) ||
+ set_error_if_http_failed (priv->msg, &error))
+ {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+ else
+ g_simple_async_result_set_op_res_gboolean (result, TRUE);
+
+ priv->finished_cb = NULL;
+ priv->cancelled_cb = NULL;
+ soup_output_stream_done_io (stream);
+
+ g_simple_async_result_complete (result);
+}
+
+static void
+soup_output_stream_finished (SoupMessage *msg, gpointer stream)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+
+ priv->finished = TRUE;
+
+ g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_output_stream_finished), stream);
+ close_async_done (stream);
+}
+
+static void
+soup_output_stream_close_async (GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SoupOutputStreamPrivate *priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (stream),
+ callback, user_data,
+ soup_output_stream_close_async);
+
+ if (priv->size > 0 && priv->offset != priv->size)
+ {
+ GError *error;
+
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ "File is incomplete");
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ g_simple_async_result_complete_in_idle (result);
+ return;
+ }
+
+ priv->result = result;
+ priv->cancelled_cb = close_async_done;
+ g_signal_connect (priv->msg, "finished",
+ G_CALLBACK (soup_output_stream_finished), stream);
+ soup_output_stream_prepare_for_io (stream, cancellable);
+}
+
+static gboolean
+soup_output_stream_close_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* Failures handled in generic close_finish code */
+ return TRUE;
+}
diff --git a/trunk/daemon/soup-output-stream.h b/trunk/daemon/soup-output-stream.h
new file mode 100644
index 00000000..f8412fda
--- /dev/null
+++ b/trunk/daemon/soup-output-stream.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SOUP_OUTPUT_STREAM_H__
+#define __SOUP_OUTPUT_STREAM_H__
+
+#include <gio/gio.h>
+#include <libsoup/soup-types.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_OUTPUT_STREAM (soup_output_stream_get_type ())
+#define SOUP_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_OUTPUT_STREAM, SoupOutputStream))
+#define SOUP_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SOUP_TYPE_OUTPUT_STREAM, SoupOutputStreamClass))
+#define SOUP_IS_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_OUTPUT_STREAM))
+#define SOUP_IS_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_OUTPUT_STREAM))
+#define SOUP_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_OUTPUT_STREAM, SoupOutputStreamClass))
+
+typedef struct SoupOutputStream SoupOutputStream;
+typedef struct SoupOutputStreamClass SoupOutputStreamClass;
+
+struct SoupOutputStream
+{
+ GOutputStream parent;
+
+};
+
+struct SoupOutputStreamClass
+{
+ GOutputStreamClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+};
+
+GType soup_output_stream_get_type (void) G_GNUC_CONST;
+
+GOutputStream *soup_output_stream_new (SoupSession *session,
+ SoupMessage *msg,
+ goffset size);
+
+G_END_DECLS
+
+#endif /* __SOUP_OUTPUT_STREAM_H__ */
diff --git a/trunk/daemon/trash.mount.in b/trunk/daemon/trash.mount.in
new file mode 100644
index 00000000..2f161634
--- /dev/null
+++ b/trunk/daemon/trash.mount.in
@@ -0,0 +1,5 @@
+[Mount]
+Type=trash
+Exec=@libexecdir@/gvfsd-trash
+AutoMount=true
+
diff --git a/trunk/daemon/trashlib/COPYING b/trunk/daemon/trashlib/COPYING
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/trunk/daemon/trashlib/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/trunk/daemon/trashlib/Makefile.am b/trunk/daemon/trashlib/Makefile.am
new file mode 100644
index 00000000..323c9425
--- /dev/null
+++ b/trunk/daemon/trashlib/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LIBRARIES = libtrash.a
+
+libtrash_a_CFLAGS = $(GLIB_CFLAGS)
+
+libtrash_a_SOURCES = \
+ dirwatch.h \
+ dirwatch.c \
+ trashdir.h \
+ trashdir.c \
+ trashitem.h \
+ trashitem.c \
+ trashwatcher.h \
+ trashwatcher.c \
+ trashexpunge.h \
+ trashexpunge.c
diff --git a/trunk/daemon/trashlib/dirwatch.c b/trunk/daemon/trashlib/dirwatch.c
new file mode 100644
index 00000000..f2bc6924
--- /dev/null
+++ b/trunk/daemon/trashlib/dirwatch.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include <sys/stat.h>
+
+#include "dirwatch.h"
+
+/* DirWatch
+ *
+ * a directory watcher utility for use by the trash:/ backend.
+ *
+ * A DirWatch monitors a given directory for existence under a very
+ * specific set of circumstances. When the directory comes into
+ * existence, the create() callback is invoked. When the directory
+ * stops existing the destroy() callback is invoked. If the directory
+ * initially exists, then create() is invoked before the call to
+ * dir_watch_new() returns.
+ *
+ * The directory to watch is considered to exist only if it is a
+ * directory (and not a symlink) and its parent directory also exists.
+ * A topdir must be given, which is always assumed to "exist".
+ *
+ * For example, if '/mnt/disk/.Trash/1000/files/' is monitored with
+ * '/mnt/disk/' as a topdir then the following conditions must be true
+ * in order for the directory to be reported as existing:
+ *
+ * /mnt/disk/ is blindly assumed to exist
+ * /mnt/disk/.Trash must be a directory (not a symlink)
+ * /mnt/disk/.Trash/1000 must be a directory (not a symlink)
+ * /mnt/disk/.Trash/1000/files must be a directory (not a symlink)
+ *
+ * If any of these ceases to be true (even momentarily), the directory
+ * will be reported as having been destroyed. create() and destroy()
+ * callbacks are never issued spuriously (ie: two calls to one
+ * callback will never occur in a row). Events where the directory
+ * exists momentarily might be missed, but events where the directory
+ * stops existing momentarily will (hopefully) always be reported.
+ * The first call (if it happens) will always be to create().
+ *
+ * check() is only ever called in response to a call to
+ * dir_watch_check() in which case it will be called only if the
+ * watched directory was marked as having existed before the check and
+ * is found to still exist. This facilitates the checking that has to
+ * occur in that case (ie: check the contents of the directory to make
+ * sure that they are also unchanged).
+ *
+ * This implementation is currently tweaked a bit for how GFileMonitor
+ * currently works with inotify. If GFileMonitor's implementation is
+ * changed it might be a good idea to take another look at this code.
+ */
+
+struct OPAQUE_TYPE__DirWatch
+{
+ GFile *directory;
+ GFile *topdir;
+
+ DirWatchFunc create;
+ DirWatchFunc check;
+ DirWatchFunc destroy;
+ gpointer user_data;
+ gboolean state;
+
+ DirWatch *parent;
+
+ GFileMonitor *parent_monitor;
+};
+
+#ifdef DIR_WATCH_DEBUG
+# define dir_watch_created(watch) \
+ G_STMT_START { \
+ char *path = g_file_get_path ((watch)->directory); \
+ g_print (">> created '%s'\n", path); \
+ g_free (path); \
+ (watch)->create ((watch)->user_data); \
+ } G_STMT_END
+
+# define dir_watch_destroyed(watch) \
+ G_STMT_START { \
+ char *path = g_file_get_path ((watch)->directory); \
+ g_print (">> destroyed '%s'\n", path); \
+ g_free (path); \
+ (watch)->destroy ((watch)->user_data); \
+ } G_STMT_END
+#else
+# define dir_watch_created(watch) (watch)->create ((watch)->user_data)
+# define dir_watch_destroyed(watch) (watch)->destroy ((watch)->user_data)
+#endif
+
+#ifdef DIR_WATCH_DEBUG
+#include <errno.h>
+#endif
+
+static gboolean
+dir_exists (GFile *file)
+{
+ gboolean result;
+ struct stat buf;
+ char *path;
+
+ path = g_file_get_path (file);
+#ifdef DIR_WATCH_DEBUG
+ errno = 0;
+#endif
+ result = !lstat (path, &buf) && S_ISDIR (buf.st_mode);
+
+#ifdef DIR_WATCH_DEBUG
+ g_print (" lstat ('%s') -> is%s a directory (%s)\n",
+ path, result ? "" : " not", g_strerror (errno));
+#endif
+
+ g_free (path);
+
+ return result;
+}
+
+static void
+dir_watch_parent_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ DirWatch *watch = user_data;
+
+ g_assert (watch->parent_monitor == monitor);
+
+ if (!g_file_equal (file, watch->directory))
+ return;
+
+ if (event_type == G_FILE_MONITOR_EVENT_CREATED)
+ {
+ if (watch->state)
+ return;
+
+ /* we were just created. ensure that it's a directory. */
+ if (dir_exists (file))
+ {
+ /* we're official now. report it. */
+ watch->state = TRUE;
+ dir_watch_created (watch);
+ }
+ }
+ else if (event_type == G_FILE_MONITOR_EVENT_DELETED)
+ {
+ if (!watch->state)
+ return;
+
+ watch->state = FALSE;
+ dir_watch_destroyed (watch);
+ }
+}
+
+static void
+dir_watch_recursive_create (gpointer user_data)
+{
+ DirWatch *watch = user_data;
+ GFile *parent;
+
+ g_assert (watch->parent_monitor == NULL);
+
+ parent = g_file_get_parent (watch->directory);
+ watch->parent_monitor = g_file_monitor_directory (parent, 0,
+ NULL, NULL);
+ g_object_unref (parent);
+ g_signal_connect (watch->parent_monitor, "changed",
+ G_CALLBACK (dir_watch_parent_changed), watch);
+
+ /* check if directory was created before we started to monitor */
+ if (dir_exists (watch->directory))
+ {
+ watch->state = TRUE;
+ dir_watch_created (watch);
+ }
+}
+
+static void
+dir_watch_recursive_check (gpointer user_data)
+{
+ DirWatch *watch = user_data;
+ gboolean exists;
+
+ exists = dir_exists (watch->directory);
+
+ if (watch->state && exists)
+ watch->check (watch->user_data);
+
+ else if (!watch->state && exists)
+ {
+ watch->state = TRUE;
+ dir_watch_created (watch);
+ }
+ else if (watch->state && !exists)
+ {
+ watch->state = FALSE;
+ dir_watch_destroyed (watch);
+ }
+}
+
+static void
+dir_watch_recursive_destroy (gpointer user_data)
+{
+ DirWatch *watch = user_data;
+
+ /* exactly one monitor should be active */
+ g_assert (watch->parent_monitor != NULL);
+
+ /* if we were monitoring the directory... */
+ if (watch->state)
+ {
+ dir_watch_destroyed (watch);
+ watch->state = FALSE;
+ }
+
+ g_object_unref (watch->parent_monitor);
+ watch->parent_monitor = NULL;
+}
+
+DirWatch *
+dir_watch_new (GFile *directory,
+ GFile *topdir,
+ DirWatchFunc create,
+ DirWatchFunc check,
+ DirWatchFunc destroy,
+ gpointer user_data)
+{
+ DirWatch *watch;
+
+ watch = g_slice_new0 (DirWatch);
+ watch->create = create;
+ watch->check = check;
+ watch->destroy = destroy;
+ watch->user_data = user_data;
+
+ watch->directory = g_object_ref (directory);
+ watch->topdir = g_object_ref (topdir);
+
+ /* the top directory always exists */
+ if (g_file_equal (directory, topdir))
+ {
+ dir_watch_created (watch);
+ watch->state = TRUE;
+ }
+
+ else
+ {
+ GFile *parent;
+
+ parent = g_file_get_parent (directory);
+ g_assert (parent != NULL);
+
+ watch->parent = dir_watch_new (parent, topdir,
+ dir_watch_recursive_create,
+ dir_watch_recursive_check,
+ dir_watch_recursive_destroy,
+ watch);
+
+ g_object_unref (parent);
+ }
+
+ return watch;
+}
+
+void
+dir_watch_free (DirWatch *watch)
+{
+ if (watch != NULL)
+ {
+ if (watch->parent_monitor)
+ g_object_unref (watch->parent_monitor);
+
+ g_object_unref (watch->directory);
+ g_object_unref (watch->topdir);
+
+ dir_watch_free (watch->parent);
+
+ g_slice_free (DirWatch, watch);
+ }
+}
+
+/**
+ * dir_watch_check:
+ * @watch: a #DirWatch
+ *
+ * Emit missed events.
+ *
+ * This function is called on a DirWatch that might have missed events
+ * (because it is watching on an NFS mount, for example).
+ *
+ * This function will manually check if any directories have come into
+ * or gone out of existence and will emit created or destroyed callbacks
+ * as appropriate.
+ *
+ * Additionally, if a directory is found to still exist, the checked
+ * callback will be emitted.
+ **/
+void
+dir_watch_check (DirWatch *watch)
+{
+ if (watch->parent == NULL)
+ {
+ g_assert (watch->state);
+
+ watch->check (watch->user_data);
+ return;
+ }
+
+ dir_watch_check (watch->parent);
+}
diff --git a/trunk/daemon/trashlib/dirwatch.h b/trunk/daemon/trashlib/dirwatch.h
new file mode 100644
index 00000000..58bb7b05
--- /dev/null
+++ b/trunk/daemon/trashlib/dirwatch.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _dirwatch_h_
+#define _dirwatch_h_
+
+#include <gio/gio.h>
+
+typedef void (*DirWatchFunc) (gpointer user_data);
+typedef struct OPAQUE_TYPE__DirWatch DirWatch;
+
+DirWatch *dir_watch_new (GFile *directory,
+ GFile *topdir,
+ DirWatchFunc create,
+ DirWatchFunc check,
+ DirWatchFunc destroy,
+ gpointer user_data);
+
+void dir_watch_check (DirWatch *watch);
+
+void dir_watch_free (DirWatch *watch);
+
+#endif /* _dirwatch_h_ */
diff --git a/trunk/daemon/trashlib/trashdir.c b/trunk/daemon/trashlib/trashdir.c
new file mode 100644
index 00000000..dd110e3c
--- /dev/null
+++ b/trunk/daemon/trashlib/trashdir.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include "trashdir.h"
+
+#include <sys/stat.h>
+#include <string.h>
+
+#include "dirwatch.h"
+
+struct OPAQUE_TYPE__TrashDir
+{
+ TrashRoot *root;
+ GSList *items;
+
+ GFile *directory;
+ GFile *topdir;
+ gboolean is_homedir;
+
+ DirWatch *watch;
+ GFileMonitor *monitor;
+};
+
+static gint
+compare_basename (gconstpointer a,
+ gconstpointer b)
+{
+ GFile *file_a, *file_b;
+ char *name_a, *name_b;
+ gint result;
+
+ file_a = (GFile *) a;
+ file_b = (GFile *) b;
+
+ name_a = g_file_get_basename (file_a);
+ name_b = g_file_get_basename (file_b);
+
+ result = strcmp (name_a, name_b);
+
+ g_free (name_a);
+ g_free (name_b);
+
+ return result;
+}
+
+static void
+trash_dir_set_files (TrashDir *dir,
+ GSList *items)
+{
+ GSList **old, *new;
+
+ items = g_slist_sort (items, (GCompareFunc) compare_basename);
+ old = &dir->items;
+ new = items;
+
+ while (new || *old)
+ {
+ int result;
+
+ if ((result = (new == NULL) - (*old == NULL)) == 0)
+ result = compare_basename (new->data, (*old)->data);
+
+ if (result < 0)
+ {
+ /* new entry. add it. */
+ *old = g_slist_prepend (*old, new->data); /* take reference */
+ old = &(*old)->next;
+ trash_root_add_item (dir->root, new->data, dir->is_homedir);
+ new = new->next;
+ }
+ else if (result > 0)
+ {
+ /* old entry. remove it. */
+ trash_root_remove_item (dir->root, (*old)->data, dir->is_homedir);
+ g_object_unref ((*old)->data);
+ *old = g_slist_delete_link (*old, *old);
+ }
+ else
+ {
+ /* match. no change. */
+ old = &(*old)->next;
+ g_object_unref (new->data);
+ new = new->next;
+ }
+ }
+
+ g_slist_free (items);
+
+ trash_root_thaw (dir->root);
+}
+
+static void
+trash_dir_empty (TrashDir *dir)
+{
+ trash_dir_set_files (dir, NULL);
+}
+
+static void
+trash_dir_enumerate (TrashDir *dir)
+{
+ GFileEnumerator *enumerator;
+ GSList *files = NULL;
+
+ enumerator = g_file_enumerate_children (dir->directory,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ if (enumerator)
+ {
+ GFileInfo *info;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+ {
+ GFile *file;
+
+ file = g_file_get_child (dir->directory,
+ g_file_info_get_name (info));
+ files = g_slist_prepend (files, file);
+
+ g_object_unref (info);
+ }
+
+ g_object_unref (enumerator);
+ }
+
+ trash_dir_set_files (dir, files); /* consumes files */
+}
+
+static void
+trash_dir_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ TrashDir *dir = user_data;
+
+ if (event_type == G_FILE_MONITOR_EVENT_CREATED)
+ trash_root_add_item (dir->root, file, dir->is_homedir);
+
+ else if (event_type == G_FILE_MONITOR_EVENT_DELETED)
+ trash_root_remove_item (dir->root, file, dir->is_homedir);
+
+ else if (event_type == G_FILE_MONITOR_EVENT_PRE_UNMOUNT ||
+ event_type == G_FILE_MONITOR_EVENT_UNMOUNTED)
+ ;
+
+ else
+ {
+ static gboolean already_did_warning;
+ char *dirname;
+ char *name;
+
+ g_warning ("*** Unsupported operation detected on trash directory");
+ if (!already_did_warning)
+ {
+ g_warning (" A trash files/ directory should only have files "
+ "linked or unlinked (via moves or deletes). Some other "
+ "operation has been detected on a file in the directory "
+ "(eg: a file has been modified). Likely, the data "
+ "reported by the trash backend will now be "
+ "inconsistent.");
+ already_did_warning = TRUE;
+ }
+
+ name = file ? g_file_get_basename (file) : NULL;
+ dirname = g_file_get_path (dir->directory);
+ g_warning (" dir: %s, file: %s, type: %d\n\n",
+ dirname, name, event_type);
+ g_free (dirname);
+ g_free (name);
+ }
+
+ trash_root_thaw (dir->root);
+}
+
+static void
+trash_dir_created (gpointer user_data)
+{
+ TrashDir *dir = user_data;
+
+ g_assert (dir->monitor == NULL);
+ dir->monitor = g_file_monitor_directory (dir->directory, 0, NULL, NULL);
+ g_signal_connect (dir->monitor, "changed",
+ G_CALLBACK (trash_dir_changed), dir);
+ trash_dir_enumerate (dir);
+}
+
+static void
+trash_dir_check (gpointer user_data)
+{
+ TrashDir *dir = user_data;
+
+ trash_dir_enumerate (dir);
+}
+
+static void
+trash_dir_destroyed (gpointer user_data)
+{
+ TrashDir *dir = user_data;
+
+ g_assert (dir->monitor != NULL);
+ g_object_unref (dir->monitor);
+ dir->monitor = NULL;
+
+ trash_dir_empty (dir);
+}
+
+void
+trash_dir_watch (TrashDir *dir)
+{
+ g_assert (dir->monitor == NULL);
+ g_assert (dir->watch == NULL);
+
+ /* start monitoring after a period of not monitoring.
+ *
+ * there are two possible cases here:
+ * 1) the directory now exists
+ * - we have to rescan the directory to ensure that we notice
+ * any changes that have occured since we last looked
+ *
+ * 2) the directory does not exist
+ * - if it existed last time we looked then we may have stale
+ * toplevel items that need to be removed.
+ *
+ * in case 1, trash_dir_created() will be called from
+ * dir_watch_new(). it calls trash_enumerate() itself.
+ *
+ * in case 2, no other function will be called and we must manually
+ * call trash_dir_empty().
+ *
+ * we can tell if case 1 happened because trash_dir_created() also
+ * sets the dir->monitor.
+ */
+ dir->watch = dir_watch_new (dir->directory, dir->topdir,
+ trash_dir_created,
+ trash_dir_check,
+ trash_dir_destroyed,
+ dir);
+
+ if (dir->monitor == NULL)
+ /* case 2 */
+ trash_dir_empty (dir);
+}
+
+void
+trash_dir_unwatch (TrashDir *dir)
+{
+ g_assert (dir->watch != NULL);
+
+ /* stop monitoring.
+ *
+ * in all cases, we just fall silent.
+ */
+
+ if (dir->monitor != NULL)
+ {
+ g_object_unref (dir->monitor);
+ dir->monitor = NULL;
+ }
+
+ dir_watch_free (dir->watch);
+ dir->watch = NULL;
+}
+
+static gboolean
+dir_exists (GFile *directory,
+ GFile *top_dir)
+{
+ gboolean result = FALSE;
+ GFile *parent;
+
+ if (g_file_equal (directory, top_dir))
+ return TRUE;
+
+ parent = g_file_get_parent (directory);
+
+ if (dir_exists (parent, top_dir))
+ {
+ struct stat buf;
+ gchar *path;
+
+ path = g_file_get_path (directory);
+ result = !lstat (path, &buf) && S_ISDIR (buf.st_mode);
+
+ g_free (path);
+ }
+
+ g_object_unref (parent);
+
+ return result;
+}
+
+void
+trash_dir_rescan (TrashDir *dir)
+{
+ if (dir->watch)
+ dir_watch_check (dir->watch);
+
+ else if (dir_exists (dir->directory, dir->topdir))
+ trash_dir_enumerate (dir);
+
+ else
+ trash_dir_empty (dir);
+}
+
+static trash_dir_ui_hook ui_hook;
+
+TrashDir *
+trash_dir_new (TrashRoot *root,
+ gboolean watching,
+ gboolean is_homedir,
+ const char *mount_point,
+ const char *format,
+ ...)
+{
+ TrashDir *dir;
+ va_list ap;
+ char *rel;
+
+ va_start (ap, format);
+ rel = g_strdup_vprintf (format, ap);
+ va_end (ap);
+
+ dir = g_slice_new (TrashDir);
+
+ dir->root = root;
+ dir->items = NULL;
+ dir->topdir = g_file_new_for_path (mount_point);
+ dir->directory = g_file_get_child (dir->topdir, rel);
+ dir->monitor = NULL;
+ dir->is_homedir = is_homedir;
+
+ if (watching)
+ dir->watch = dir_watch_new (dir->directory,
+ dir->topdir,
+ trash_dir_created,
+ trash_dir_check,
+ trash_dir_destroyed,
+ dir);
+ else
+ dir->watch = NULL;
+
+ if (ui_hook)
+ ui_hook (dir, dir->directory);
+
+ g_free (rel);
+
+ return dir;
+}
+
+void
+trash_dir_set_ui_hook (trash_dir_ui_hook _ui_hook)
+{
+ ui_hook = _ui_hook;
+}
+
+void
+trash_dir_free (TrashDir *dir)
+{
+ if (dir->watch)
+ dir_watch_free (dir->watch);
+
+ if (dir->monitor)
+ g_object_unref (dir->monitor);
+
+ trash_dir_set_files (dir, NULL);
+
+ g_object_unref (dir->directory);
+ g_object_unref (dir->topdir);
+
+ g_slice_free (TrashDir, dir);
+}
diff --git a/trunk/daemon/trashlib/trashdir.h b/trunk/daemon/trashlib/trashdir.h
new file mode 100644
index 00000000..5612f9ba
--- /dev/null
+++ b/trunk/daemon/trashlib/trashdir.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _trashdir_h_
+#define _trashdir_h_
+
+#include <gio/gio.h>
+
+#include "trashitem.h"
+
+typedef struct OPAQUE_TYPE__TrashDir TrashDir;
+
+typedef void (*trash_dir_ui_hook) (TrashDir *dir,
+ GFile *directory);
+
+TrashDir *trash_dir_new (TrashRoot *root,
+ gboolean watching,
+ gboolean is_homedir,
+ const char *mount_point,
+ const char *format,
+ ...);
+
+void trash_dir_free (TrashDir *dir);
+
+void trash_dir_watch (TrashDir *dir);
+void trash_dir_unwatch (TrashDir *dir);
+void trash_dir_rescan (TrashDir *dir);
+
+void trash_dir_set_ui_hook (trash_dir_ui_hook ui_hook);
+
+#endif /* _trashdir_h_ */
diff --git a/trunk/daemon/trashlib/trashexpunge.c b/trunk/daemon/trashlib/trashexpunge.c
new file mode 100644
index 00000000..782be54e
--- /dev/null
+++ b/trunk/daemon/trashlib/trashexpunge.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include "trashexpunge.h"
+
+static gsize trash_expunge_initialised;
+static GHashTable *trash_expunge_queue;
+static gboolean trash_expunge_alive;
+static GMutex *trash_expunge_lock;
+static GCond *trash_expunge_wait;
+
+static void
+trash_expunge_delete_everything_under (GFile *directory)
+{
+ GFileEnumerator *enumerator;
+
+ g_file_set_attribute_uint32 (directory,
+ G_FILE_ATTRIBUTE_UNIX_MODE, 0700,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ enumerator = g_file_enumerate_children (directory,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, NULL);
+
+ if (enumerator)
+ {
+ GFileInfo *info;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+ {
+ const gchar *basename;
+ GFile *sub;
+
+ basename = g_file_info_get_name (info);
+ sub = g_file_get_child (directory, basename);
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ trash_expunge_delete_everything_under (sub);
+
+ /* do the delete here */
+ g_file_delete (sub, NULL, NULL);
+
+ g_object_unref (info);
+ g_object_unref (sub);
+ }
+ g_object_unref (enumerator);
+ }
+}
+
+static gboolean
+just_return_true (gpointer a,
+ gpointer b,
+ gpointer c)
+{
+ return TRUE;
+}
+
+static gpointer
+trash_expunge_thread (gpointer data)
+{
+ GTimeVal timeval;
+
+ g_mutex_lock (trash_expunge_lock);
+
+ do
+ {
+ while (g_hash_table_size (trash_expunge_queue))
+ {
+ GFile *directory;
+
+ directory = g_hash_table_find (trash_expunge_queue,
+ just_return_true, NULL);
+ g_hash_table_remove (trash_expunge_queue, directory);
+
+ g_mutex_unlock (trash_expunge_lock);
+ trash_expunge_delete_everything_under (directory);
+ g_mutex_lock (trash_expunge_lock);
+
+ g_object_unref (directory);
+ }
+
+ g_get_current_time (&timeval);
+ g_time_val_add (&timeval, 60 * 1000000); /* 1min */
+ }
+ while (g_cond_timed_wait (trash_expunge_wait,
+ trash_expunge_lock,
+ &timeval));
+
+ trash_expunge_alive = FALSE;
+
+ g_mutex_unlock (trash_expunge_lock);
+
+ return NULL;
+}
+
+void
+trash_expunge (GFile *directory)
+{
+ if G_UNLIKELY (g_once_init_enter (&trash_expunge_initialised))
+ {
+ trash_expunge_queue = g_hash_table_new (g_file_hash,
+ (GEqualFunc) g_file_equal);
+ trash_expunge_lock = g_mutex_new ();
+ trash_expunge_wait = g_cond_new ();
+
+ g_once_init_leave (&trash_expunge_initialised, 1);
+ }
+
+ g_mutex_lock (trash_expunge_lock);
+
+ if (!g_hash_table_lookup (trash_expunge_queue, directory))
+ g_hash_table_insert (trash_expunge_queue,
+ g_object_ref (directory),
+ directory);
+
+ if (trash_expunge_alive == FALSE)
+ {
+ GThread *thread;
+
+ thread = g_thread_create (trash_expunge_thread, NULL, FALSE, NULL);
+ g_assert (thread != NULL);
+ trash_expunge_alive = TRUE;
+ }
+ else
+ g_cond_signal (trash_expunge_wait);
+
+ g_mutex_unlock (trash_expunge_lock);
+}
diff --git a/trunk/daemon/trashlib/trashexpunge.h b/trunk/daemon/trashlib/trashexpunge.h
new file mode 100644
index 00000000..d6ab4f8f
--- /dev/null
+++ b/trunk/daemon/trashlib/trashexpunge.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _trashexpunger_h_
+#define _trashexpunger_h_
+
+#include <gio/gio.h>
+
+typedef struct OPAQUE_TYPE__TrashExpunger TrashExpunger;
+void trash_expunge (GFile *expunge_directory);
+
+#endif /* _trashexpunger_h_ */
diff --git a/trunk/daemon/trashlib/trashitem.c b/trunk/daemon/trashlib/trashitem.c
new file mode 100644
index 00000000..7ad79735
--- /dev/null
+++ b/trunk/daemon/trashlib/trashitem.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include "trashexpunge.h"
+#include "trashitem.h"
+
+#include <glib/gstdio.h>
+
+typedef struct
+{
+ trash_item_notify func;
+ TrashItem *item;
+ gpointer user_data;
+} NotifyClosure;
+
+struct OPAQUE_TYPE__TrashRoot
+{
+ GStaticRWLock lock;
+ GQueue *notifications;
+
+ trash_item_notify create_notify;
+ trash_item_notify delete_notify;
+ trash_size_change size_change;
+ gpointer user_data;
+
+ GHashTable *item_table;
+ gboolean is_homedir;
+ int old_size;
+};
+
+struct OPAQUE_TYPE__TrashItem
+{
+ TrashRoot *root;
+ gint ref_count;
+
+ char *escaped_name;
+ GFile *file;
+
+ GFile *original;
+ char *delete_date;
+};
+
+static char *
+trash_item_escape_name (GFile *file,
+ gboolean in_homedir)
+{
+ /*
+ * make unique names as follows:
+ *
+ * - items in home directory use their basename (never starts with '/')
+ *
+ * - if the basename starts with '\' then it is changed to '`\'
+ *
+ * - if the basename starts with '`' then it is changed to '``'
+ *
+ * - this means that home directory items never start with '\'
+ *
+ * - items in others use full path name (always starts with '/')
+ *
+ * - each '/' (including the first) is changed to '\'
+ *
+ * - this means that all of these items start with '\'
+ *
+ * - each '\' is changed to '`\'
+ *
+ * - each '`' is changed to '``'
+ */
+#define ESCAPE_SYMBOL1 '\\'
+#define ESCAPE_SYMBOL2 '`'
+
+ if (in_homedir)
+ {
+ char *basename;
+ char *escaped;
+
+ basename = g_file_get_basename (file);
+
+ if (basename[0] != ESCAPE_SYMBOL1 && basename[0] != ESCAPE_SYMBOL2)
+ return basename;
+
+ escaped = g_strdup_printf ("%c%s", ESCAPE_SYMBOL2, basename);
+ g_free (basename);
+
+ return escaped;
+ }
+ else
+ {
+ char *uri, *src, *dest, *escaped;
+ int need_bytes = 0;
+
+ uri = g_file_get_uri (file);
+ g_assert (g_str_has_prefix (uri, "file:///"));
+
+ src = uri + 7; /* keep the first '/' */
+ while (*src)
+ {
+ if (*src == ESCAPE_SYMBOL1 || *src == ESCAPE_SYMBOL2)
+ need_bytes += 2;
+ else
+ need_bytes++;
+
+ src++;
+ }
+
+ escaped = g_malloc (need_bytes + 1);
+
+ dest = escaped;
+ src = uri + 7;
+ while (*src)
+ {
+ if (*src == ESCAPE_SYMBOL1 || *src == ESCAPE_SYMBOL2)
+ {
+ *dest++ = ESCAPE_SYMBOL2;
+ *dest++ = *src;
+ }
+ else if (*src == '/')
+ *dest++ = ESCAPE_SYMBOL1;
+ else
+ *dest++ = *src;
+
+ src++;
+ }
+
+ g_free (uri);
+ *dest = '\0';
+
+ return escaped;
+ }
+}
+
+static void
+trash_item_get_trashinfo (GFile *path,
+ GFile **original,
+ char **date)
+{
+ GFile *files, *trashdir;
+ GKeyFile *keyfile;
+ char *trashpath;
+ char *trashinfo;
+ char *basename;
+
+ files = g_file_get_parent (path);
+ trashdir = g_file_get_parent (files);
+ trashpath = g_file_get_path (trashdir);
+ g_object_unref (files);
+
+ basename = g_file_get_basename (path);
+
+ trashinfo = g_strdup_printf ("%s/info/%s.trashinfo", trashpath, basename);
+ g_free (trashpath);
+ g_free (basename);
+
+ keyfile = g_key_file_new ();
+
+ *original = NULL;
+ *date = NULL;
+
+ if (g_key_file_load_from_file (keyfile, trashinfo, 0, NULL))
+ {
+ char *orig;
+
+ orig = g_key_file_get_string (keyfile,
+ "Trash Info", "Path",
+ NULL);
+
+ if (orig == NULL)
+ *original = NULL;
+
+ else if (g_path_is_absolute (orig))
+ *original = g_file_new_for_path (orig);
+
+ else
+ {
+ GFile *rootdir;
+
+ rootdir = g_file_get_parent (trashdir);
+ *original = g_file_get_child (rootdir, orig);
+ g_object_unref (rootdir);
+ }
+
+ g_free (orig);
+
+ *date = g_key_file_get_string (keyfile,
+ "Trash Info", "DeletionDate",
+ NULL);
+ }
+
+ g_object_unref (trashdir);
+ g_key_file_free (keyfile);
+ g_free (trashinfo);
+}
+
+static TrashItem *
+trash_item_new (TrashRoot *root,
+ GFile *file,
+ gboolean in_homedir)
+{
+ TrashItem *item;
+
+ item = g_slice_new (TrashItem);
+ item->root = root;
+ item->ref_count = 1;
+ item->file = g_object_ref (file);
+ item->escaped_name = trash_item_escape_name (file, in_homedir);
+ trash_item_get_trashinfo (item->file, &item->original, &item->delete_date);
+
+ return item;
+}
+
+static TrashItem *
+trash_item_ref (TrashItem *item)
+{
+ g_atomic_int_inc (&item->ref_count);
+ return item;
+}
+
+void
+trash_item_unref (TrashItem *item)
+{
+ if (g_atomic_int_dec_and_test (&item->ref_count))
+ {
+ g_object_unref (item->file);
+
+ if (item->original)
+ g_object_unref (item->original);
+
+ g_free (item->delete_date);
+ g_free (item->escaped_name);
+
+ g_slice_free (TrashItem, item);
+ }
+}
+
+const char *
+trash_item_get_escaped_name (TrashItem *item)
+{
+ return item->escaped_name;
+}
+
+const char *
+trash_item_get_delete_date (TrashItem *item)
+{
+ return item->delete_date;
+}
+
+GFile *
+trash_item_get_original (TrashItem *item)
+{
+ return item->original;
+}
+
+GFile *
+trash_item_get_file (TrashItem *item)
+{
+ return item->file;
+}
+
+static void
+trash_item_queue_notify (TrashItem *item,
+ trash_item_notify func)
+{
+ NotifyClosure *closure;
+
+ closure = g_slice_new (NotifyClosure);
+ closure->func = func;
+ closure->item = trash_item_ref (item);
+ closure->user_data = item->root->user_data;
+
+ g_queue_push_tail (item->root->notifications, closure);
+}
+
+static void
+trash_item_invoke_closure (NotifyClosure *closure)
+{
+ closure->func (closure->item, closure->user_data);
+ trash_item_unref (closure->item);
+ g_slice_free (NotifyClosure, closure);
+}
+
+void
+trash_root_thaw (TrashRoot *root)
+{
+ NotifyClosure *closure;
+ gboolean size_changed;
+ int size;
+
+ /* send notifications until we have none */
+ while (TRUE)
+ {
+ g_static_rw_lock_writer_lock (&root->lock);
+ if (g_queue_is_empty (root->notifications))
+ break;
+
+ closure = g_queue_pop_head (root->notifications);
+ g_static_rw_lock_writer_unlock (&root->lock);
+
+ trash_item_invoke_closure (closure);
+ }
+
+ /* still holding lock... */
+ size = g_hash_table_size (root->item_table);
+ size_changed = root->old_size != size;
+ root->old_size = size;
+
+ g_static_rw_lock_writer_unlock (&root->lock);
+
+ if (size_changed)
+ root->size_change (root->user_data);
+}
+
+static void
+trash_item_removed (gpointer data)
+{
+ TrashItem *item = data;
+
+ trash_item_queue_notify (item, item->root->delete_notify);
+ trash_item_unref (item);
+}
+
+TrashRoot *
+trash_root_new (trash_item_notify create,
+ trash_item_notify delete,
+ trash_size_change size_change,
+ gpointer user_data)
+{
+ TrashRoot *root;
+
+ root = g_slice_new (TrashRoot);
+ g_static_rw_lock_init (&root->lock);
+ root->create_notify = create;
+ root->delete_notify = delete;
+ root->size_change = size_change;
+ root->user_data = user_data;
+ root->notifications = g_queue_new ();
+ root->item_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, trash_item_removed);
+ root->old_size = 0;
+
+ return root;
+}
+
+void
+trash_root_free (TrashRoot *root)
+{
+ g_hash_table_destroy (root->item_table);
+
+ while (!g_queue_is_empty (root->notifications))
+ {
+ NotifyClosure *closure;
+
+ closure = g_queue_pop_head (root->notifications);
+ trash_item_unref (closure->item);
+ g_slice_free (NotifyClosure, closure);
+ }
+ g_queue_free (root->notifications);
+
+ g_slice_free (TrashRoot, root);
+}
+
+void
+trash_root_add_item (TrashRoot *list,
+ GFile *file,
+ gboolean in_homedir)
+{
+ TrashItem *item;
+
+ item = trash_item_new (list, file, in_homedir);
+
+ g_static_rw_lock_writer_lock (&list->lock);
+
+ if (g_hash_table_lookup (list->item_table, item->escaped_name))
+ {
+ g_static_rw_lock_writer_unlock (&list->lock);
+
+ /* already exists... */
+ trash_item_unref (item);
+ return;
+ }
+
+ g_hash_table_insert (list->item_table, item->escaped_name, item);
+ trash_item_queue_notify (item, item->root->create_notify);
+
+ g_static_rw_lock_writer_unlock (&list->lock);
+}
+
+void
+trash_root_remove_item (TrashRoot *list,
+ GFile *file,
+ gboolean in_homedir)
+{
+ char *escaped;
+
+ escaped = trash_item_escape_name (file, in_homedir);
+
+ g_static_rw_lock_writer_lock (&list->lock);
+ g_hash_table_remove (list->item_table, escaped);
+ g_static_rw_lock_writer_unlock (&list->lock);
+
+ g_free (escaped);
+}
+
+GList *
+trash_root_get_items (TrashRoot *root)
+{
+ GList *items, *node;
+
+ g_static_rw_lock_reader_lock (&root->lock);
+
+ items = g_hash_table_get_values (root->item_table);
+ for (node = items; node; node = node->next)
+ trash_item_ref (node->data);
+
+ g_static_rw_lock_reader_unlock (&root->lock);
+
+ return items;
+}
+
+void
+trash_item_list_free (GList *list)
+{
+ GList *node;
+
+ for (node = list; node; node = node->next)
+ trash_item_unref (node->data);
+ g_list_free (list);
+}
+
+TrashItem *
+trash_root_lookup_item (TrashRoot *root,
+ const char *escaped)
+{
+ TrashItem *item;
+
+ g_static_rw_lock_reader_lock (&root->lock);
+
+ if ((item = g_hash_table_lookup (root->item_table, escaped)))
+ trash_item_ref (item);
+
+ g_static_rw_lock_reader_unlock (&root->lock);
+
+ return item;
+}
+
+int
+trash_root_get_n_items (TrashRoot *root)
+{
+ int size;
+
+ g_static_rw_lock_reader_lock (&root->lock);
+ size = g_hash_table_size (root->item_table);
+ g_static_rw_lock_reader_unlock (&root->lock);
+
+ return size;
+}
+
+gboolean
+trash_item_delete (TrashItem *item,
+ GError **error)
+{
+ gboolean success;
+ GFile *expunged;
+ guint unique;
+ guint i;
+
+ expunged = g_file_resolve_relative_path (item->file,
+ "../../expunged");
+ g_file_make_directory_with_parents (expunged, NULL, NULL);
+ unique = g_random_int ();
+
+ for (success = FALSE, i = 0; !success && i < 1000; i++)
+ {
+ GFile *temp_name;
+ char buffer[16];
+
+ g_sprintf (buffer, "%u", unique + i);
+ temp_name = g_file_get_child (expunged, buffer);
+
+ /* "restore" the item into the expunged folder */
+ if (trash_item_restore (item, temp_name, NULL))
+ {
+ trash_expunge (expunged);
+ success = TRUE;
+ }
+
+ g_object_unref (temp_name);
+ }
+
+ g_object_unref (expunged);
+
+ if (!success)
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to delete the item from the trash");
+
+ return success;
+}
+
+gboolean
+trash_item_restore (TrashItem *item,
+ GFile *dest,
+ GError **error)
+{
+ if (g_file_move (item->file, dest,
+ G_FILE_COPY_OVERWRITE |
+ G_FILE_COPY_NOFOLLOW_SYMLINKS |
+ G_FILE_COPY_NO_FALLBACK_FOR_MOVE,
+ NULL, NULL, NULL, error))
+ {
+ g_static_rw_lock_writer_lock (&item->root->lock);
+ g_hash_table_remove (item->root->item_table, item->escaped_name);
+ g_static_rw_lock_writer_unlock (&item->root->lock);
+
+ {
+ GFile *trashinfo;
+ gchar *basename;
+ gchar *relname;
+
+ basename = g_file_get_basename (item->file);
+ relname = g_strdup_printf ("../../info/%s.trashinfo", basename);
+ trashinfo = g_file_resolve_relative_path (item->file, relname);
+ g_free (basename);
+ g_free (relname);
+
+ g_file_delete (trashinfo, NULL, NULL);
+ g_object_unref (trashinfo);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/trunk/daemon/trashlib/trashitem.h b/trunk/daemon/trashlib/trashitem.h
new file mode 100644
index 00000000..0fe0938e
--- /dev/null
+++ b/trunk/daemon/trashlib/trashitem.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _trashitem_h_
+#define _trashitem_h_
+
+#include <gio/gio.h>
+
+typedef struct OPAQUE_TYPE__TrashRoot TrashRoot;
+typedef struct OPAQUE_TYPE__TrashItem TrashItem;
+
+typedef void (*trash_item_notify) (TrashItem *item,
+ gpointer user_data);
+typedef void (*trash_size_change) (gpointer user_data);
+
+/* trash root -- the set of all toplevel trash items */
+TrashRoot *trash_root_new (trash_item_notify create,
+ trash_item_notify delete,
+ trash_size_change size_change,
+ gpointer user_data);
+void trash_root_free (TrashRoot *root);
+
+/* add/remove trash items (safe only from one thread) */
+void trash_root_add_item (TrashRoot *root,
+ GFile *file,
+ gboolean in_homedir);
+void trash_root_remove_item (TrashRoot *root,
+ GFile *file,
+ gboolean in_homedir);
+void trash_root_thaw (TrashRoot *root);
+
+/* query trash items, holding references (safe from any thread) */
+int trash_root_get_n_items (TrashRoot *root);
+GList *trash_root_get_items (TrashRoot *root);
+TrashItem *trash_root_lookup_item (TrashRoot *root,
+ const char *escaped);
+
+void trash_item_list_free (GList *list);
+void trash_item_unref (TrashItem *item);
+
+/* query a trash item (safe while holding a reference to it) */
+const char *trash_item_get_escaped_name (TrashItem *item);
+const char *trash_item_get_delete_date (TrashItem *item);
+GFile *trash_item_get_original (TrashItem *item);
+GFile *trash_item_get_file (TrashItem *item);
+
+/* delete a trash item (safe while holding a reference to it) */
+gboolean trash_item_delete (TrashItem *item,
+ GError **error);
+gboolean trash_item_restore (TrashItem *item,
+ GFile *dest,
+ GError **error);
+
+#endif /* _trashitem_h_ */
diff --git a/trunk/daemon/trashlib/trashwatcher.c b/trunk/daemon/trashlib/trashwatcher.c
new file mode 100644
index 00000000..a2cabfdd
--- /dev/null
+++ b/trunk/daemon/trashlib/trashwatcher.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include "trashwatcher.h"
+
+#include <gio/gunixmounts.h>
+#include <gio/gio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "trashitem.h"
+#include "trashdir.h"
+
+typedef enum
+{
+ TRASH_WATCHER_TRUSTED,
+ TRASH_WATCHER_WATCH,
+ TRASH_WATCHER_NO_WATCH,
+} WatchType;
+
+/* decide_watch_type:
+ *
+ * This function is responsible for determining what sort of watching
+ * we should do on a given mountpoint according to the type of
+ * filesystem. It must return one of the WatchType constants above.
+ *
+ * TRASH_WATCHER_TRUSTED:
+ *
+ * This is used for filesystems on which notification is supported
+ * and all file events are reliably reported. After initialisation
+ * the trash directories are never manually rescanned since any
+ * changes are already known to us from the notifications we
+ * received about them (that's where the "trust" comes in).
+ *
+ * This should be used for local filesystems such as ext3.
+ *
+ * TRASH_WATCHER_WATCH:
+ *
+ * This is used for filesystems on which notification is supported
+ * but works unreliably. Some changes to the filesystem may not
+ * be delivered by the operating system. The events which are
+ * delivered are immediately reported but events which are not
+ * delivered are not reported until the directory is manually
+ * rescanned (ie: trash_watcher_rescan() is called).
+ *
+ * This should be used for filesystems like NFS where local
+ * changes are reported by the kernel but changes made on other
+ * hosts are not.
+ *
+ * TRASH_WATCHER_NO_WATCH:
+ *
+ * Don't bother watching at all. No change events are ever
+ * delivered except while running trash_watcher_rescan().
+ *
+ * This should be used for filesystems where change notification
+ * is unsupported or is supported, but buggy enough to cause
+ * problems when using the other two options.
+ */
+static WatchType
+decide_watch_type (GUnixMountEntry *mount,
+ gboolean is_home_trash)
+{
+ const gchar *fs_type;
+
+ fs_type = g_unix_mount_get_fs_type (mount);
+
+ if (strcmp (fs_type, "nfs") == 0)
+ return TRASH_WATCHER_WATCH;
+ else
+ return TRASH_WATCHER_TRUSTED;
+}
+
+/* find the mount entry for the directory containing 'file'.
+ * used to figure out what sort of filesystem the home trash
+ * folder is sitting on.
+ */
+static GUnixMountEntry *
+find_mount_entry_for_file (GFile *file)
+{
+ GUnixMountEntry *entry;
+ char *pathname;
+
+ pathname = g_file_get_path (file);
+ do
+ {
+ char *slash;
+
+ slash = strrchr (pathname, '/');
+
+ /* leave the leading '/' in place */
+ if (slash == pathname)
+ slash++;
+
+ *slash = '\0';
+
+ entry = g_unix_mount_at (pathname, NULL);
+ }
+ while (entry == NULL && pathname[1]);
+
+ g_free (pathname);
+
+ /* if the GUnixMount stuff is gummed up, this might fail. we can't
+ * really proceed, since decide_watch_type() needs to know this.
+ */
+ g_assert (entry != NULL);
+
+ return entry;
+}
+
+typedef struct _TrashMount TrashMount;
+
+struct OPAQUE_TYPE__TrashWatcher
+{
+ TrashRoot *root;
+
+ GUnixMountMonitor *mount_monitor;
+ TrashMount *mounts;
+
+ TrashDir *homedir_trashdir;
+ WatchType homedir_type;
+
+ gboolean watching;
+};
+
+struct _TrashMount
+{
+ GUnixMountEntry *mount_entry;
+ TrashDir *dirs[2];
+ WatchType type;
+
+ TrashMount *next;
+};
+
+static void
+trash_mount_insert (TrashWatcher *watcher,
+ TrashMount ***mount_ptr_ptr,
+ GUnixMountEntry *mount_entry)
+{
+ const char *mountpoint;
+ gboolean watching;
+ TrashMount *mount;
+
+ mountpoint = g_unix_mount_get_mount_path (mount_entry);
+
+ mount = g_slice_new (TrashMount);
+ mount->mount_entry = mount_entry;
+ mount->type = decide_watch_type (mount_entry, FALSE);
+
+ watching = watcher->watching && mount->type != TRASH_WATCHER_NO_WATCH;
+
+ /* """
+ * For showing trashed files, implementations SHOULD support (1) and
+ * (2) at the same time (i.e. if both $topdir/.Trash/$uid and
+ * $topdir/.Trash-$uid are present, it should list trashed files
+ * from both of them).
+ * """
+ */
+
+ /* (1) */
+ mount->dirs[0] = trash_dir_new (watcher->root, watching, FALSE, mountpoint,
+ ".Trash/%d/files", (int) getuid ());
+
+ /* (2) */
+ mount->dirs[1] = trash_dir_new (watcher->root, watching, FALSE, mountpoint,
+ ".Trash-%d/files", (int) getuid ());
+
+ mount->next = **mount_ptr_ptr;
+
+ **mount_ptr_ptr = mount;
+ *mount_ptr_ptr = &mount->next;
+}
+
+static void
+trash_mount_remove (TrashMount **mount_ptr)
+{
+ TrashMount *mount = *mount_ptr;
+
+ /* first, the dirs */
+ trash_dir_free (mount->dirs[0]);
+ trash_dir_free (mount->dirs[1]);
+
+ /* detach from list */
+ *mount_ptr = mount->next;
+
+ g_unix_mount_free (mount->mount_entry);
+ g_slice_free (TrashMount, mount);
+}
+
+static void
+trash_watcher_remount (TrashWatcher *watcher)
+{
+ TrashMount **old;
+ GList *mounts;
+ GList *new;
+
+ mounts = g_unix_mounts_get (NULL);
+ mounts = g_list_sort (mounts, (GCompareFunc) g_unix_mount_compare);
+
+ old = &watcher->mounts;
+ new = mounts;
+
+ /* synchronise the two lists */
+ while (*old || new)
+ {
+ int result;
+
+ if (new && g_unix_mount_is_system_internal (new->data))
+ {
+ g_unix_mount_free (new->data);
+ new = new->next;
+ continue;
+ }
+
+ if ((result = (new == NULL) - (*old == NULL)) == 0)
+ result = g_unix_mount_compare (new->data, (*old)->mount_entry);
+
+ if (result < 0)
+ {
+ /* new entry. add it. */
+ trash_mount_insert (watcher, &old, new->data);
+ new = new->next;
+ }
+ else if (result > 0)
+ {
+ /* old entry. remove it. */
+ trash_mount_remove (old);
+ }
+ else
+ {
+ /* match. no change. */
+ g_unix_mount_free (new->data);
+
+ old = &(*old)->next;
+ new = new->next;
+ }
+ }
+
+ g_list_free (mounts);
+}
+
+TrashWatcher *
+trash_watcher_new (TrashRoot *root)
+{
+ GUnixMountEntry *homedir_mount;
+ GFile *homedir_trashdir;
+ TrashWatcher *watcher;
+ GFile *user_datadir;
+
+ watcher = g_slice_new (TrashWatcher);
+ watcher->root = root;
+ watcher->mounts = NULL;
+ watcher->watching = FALSE;
+ watcher->mount_monitor = g_unix_mount_monitor_new ();
+ g_signal_connect_swapped (watcher->mount_monitor, "mounts_changed",
+ G_CALLBACK (trash_watcher_remount), watcher);
+
+ user_datadir = g_file_new_for_path (g_get_user_data_dir ());
+ homedir_trashdir = g_file_get_child (user_datadir, "Trash/files");
+ homedir_mount = find_mount_entry_for_file (homedir_trashdir);
+ watcher->homedir_type = decide_watch_type (homedir_mount, TRUE);
+ watcher->homedir_trashdir = trash_dir_new (watcher->root,
+ FALSE, TRUE,
+ g_get_user_data_dir (),
+ "Trash/files");
+
+ g_unix_mount_free (homedir_mount);
+ g_object_unref (homedir_trashdir);
+ g_object_unref (user_datadir);
+
+ trash_watcher_remount (watcher);
+
+ return watcher;
+}
+
+void
+trash_watcher_free (TrashWatcher *watcher)
+{
+ g_assert_not_reached ();
+}
+
+void
+trash_watcher_watch (TrashWatcher *watcher)
+{
+ TrashMount *mount;
+
+ g_assert (!watcher->watching);
+
+ if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
+ trash_dir_watch (watcher->homedir_trashdir);
+
+ for (mount = watcher->mounts; mount; mount = mount->next)
+ if (mount->type != TRASH_WATCHER_NO_WATCH)
+ {
+ trash_dir_watch (mount->dirs[0]);
+ trash_dir_watch (mount->dirs[1]);
+ }
+
+ watcher->watching = TRUE;
+}
+
+void
+trash_watcher_unwatch (TrashWatcher *watcher)
+{
+ TrashMount *mount;
+
+ g_assert (watcher->watching);
+
+ if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
+ trash_dir_unwatch (watcher->homedir_trashdir);
+
+ for (mount = watcher->mounts; mount; mount = mount->next)
+ if (mount->type != TRASH_WATCHER_NO_WATCH)
+ {
+ trash_dir_unwatch (mount->dirs[0]);
+ trash_dir_unwatch (mount->dirs[1]);
+ }
+
+ watcher->watching = FALSE;
+}
+
+void
+trash_watcher_rescan (TrashWatcher *watcher)
+{
+ TrashMount *mount;
+
+ if (!watcher->watching || watcher->homedir_type != TRASH_WATCHER_TRUSTED)
+ trash_dir_rescan (watcher->homedir_trashdir);
+
+ for (mount = watcher->mounts; mount; mount = mount->next)
+ if (!watcher->watching || mount->type != TRASH_WATCHER_TRUSTED)
+ {
+ trash_dir_rescan (mount->dirs[0]);
+ trash_dir_rescan (mount->dirs[1]);
+ }
+}
diff --git a/trunk/daemon/trashlib/trashwatcher.h b/trunk/daemon/trashlib/trashwatcher.h
new file mode 100644
index 00000000..fbe31200
--- /dev/null
+++ b/trunk/daemon/trashlib/trashwatcher.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2008 Ryan Lortie
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _trashwatcher_h_
+#define _trashwatcher_h_
+
+#include "trashitem.h"
+
+typedef struct OPAQUE_TYPE__TrashWatcher TrashWatcher;
+
+TrashWatcher *trash_watcher_new (TrashRoot *root);
+void trash_watcher_free (TrashWatcher *watcher);
+
+void trash_watcher_watch (TrashWatcher *watcher);
+void trash_watcher_unwatch (TrashWatcher *watcher);
+void trash_watcher_rescan (TrashWatcher *watcher);
+
+#endif /* _trashitem_h_ */
diff --git a/trunk/dbus.txt b/trunk/dbus.txt
new file mode 100644
index 00000000..c9925b11
--- /dev/null
+++ b/trunk/dbus.txt
@@ -0,0 +1,83 @@
+All info for mapping uri -> dbus name + remainder path is stored in config files read by the client at startup.
+
+Each "mountpoint" in a mountpoint daemon owns a name like "org.gtk.vfs.mount.smb.$server.$share".
+It also instantiates a Mountpoint interface at /org/gtk/vfs/mount/smb/$server/$share which
+listens to operations.
+
+Each daemon that contains at least one mountpoint also registers a org.gtk.vfs.Daemon interface
+at /org/gtk/vfs/Daemon which supports operations like GetConnection and CancelOp.
+
+Clients use GetNameOwner to map uri -> mountpoint name -> owner of name -> GetConnection call so that
+it can handle multiple mountpoints in each daemon. This can be cached, and NameOwnerChanged can be used
+to invalidate the cache.
+
+----------------------
+How we map URIs
+----------------------
+
+Mapping functions needed:
+uri to mount + path
+mount + path to uri
+root parent
+
+Mapping %m://%u@%h:%p/%f
+
+ftp:
+
+m_ftp.h_%h.p_%p.u_%u
+
+smb:
+
+smb://user@/ <-> smb-root.u_user
+smb:/// <-> smb-root; path = /
+smb:///foo <-> smb-root; path = /foo, type == link
+smb://foo/ <-> smb-browse; path = /foo
+smb://foo/server -> smb-browse; path = /foo/server, type == link
+smb://user@foo/ <-> smb-browse.u_user; path = /foo
+smb://user@foo:21/ <-> smb-browse.u_user.p_21; path = /foo
+smb://domain;user@foo:21/ <-> smb-browse.d_domain.u_user.p_21; path = /foo
+smb:///foo/share/blah <-> smb-share.h_foo.s_share, path = /blah
+
+m_smb-browse.u_%u path includes hostname
+
+computer:
+
+m_computer
+
+network:
+
+m_network
+
+http:
+https:
+
+m_http(s), username+path+port in path
+
+authentication (no mount)
+
+dav:
+davs:
+
+m_dav.h_%h.p_%p.u_%u.f_%f (f== path prefix)
+
+
+nfs.h_server.p_port.u_user.f_/opt/prefix
+
+Find it by using ListNames
+
+nfs:
+
+nfs.h_server.p_port.f_/opt/prefix
+
+Find it by using ListNames
+
+sftp:
+
+trash:
+---
+
+HowTo handle:
+
+uri query part
+filename encoding - paths are raw, get utf8 via get_display_name op. (What about IRIs? Try to do utf8 paths if possible?)
+automounting? - http?
diff --git a/trunk/gconf/Makefile.am b/trunk/gconf/Makefile.am
new file mode 100644
index 00000000..7d7abb9d
--- /dev/null
+++ b/trunk/gconf/Makefile.am
@@ -0,0 +1,32 @@
+
+NULL =
+
+module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
+
+if USE_GCONF
+giomodules_LTLIBRARIES = libgiogconf.la
+endif
+
+libgiogconf_la_SOURCES = \
+ gapplookupgconf.c gapplookupgconf.h \
+ gconf-module.c \
+ $(NULL)
+
+libgiogconf_la_CFLAGS = \
+ -DG_LOG_DOMAIN=\"GVFS-GConf\" \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) \
+ $(GCONF_CFLAGS) \
+ -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+libgiogconf_la_LDFLAGS = \
+ $(module_flags) \
+ $(NULL)
+
+libgiogconf_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(GCONF_LIBS) \
+ $(NULL)
diff --git a/trunk/gconf/gapplookupgconf.c b/trunk/gconf/gapplookupgconf.c
new file mode 100644
index 00000000..5d477ba0
--- /dev/null
+++ b/trunk/gconf/gapplookupgconf.c
@@ -0,0 +1,185 @@
+
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexader Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gconf/gconf-client.h>
+
+#include "gapplookupgconf.h"
+
+
+struct _GAppLookupGConf {
+ GObject parent;
+
+};
+
+static void lookup_iface_init (GDesktopAppInfoLookupIface *iface);
+static void g_app_lookup_gconf_finalize (GObject *object);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GAppLookupGConf, g_app_lookup_gconf, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_DESKTOP_APP_INFO_LOOKUP,
+ lookup_iface_init))
+
+static void
+g_app_lookup_gconf_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (g_app_lookup_gconf_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_app_lookup_gconf_parent_class)->finalize) (object);
+}
+
+static GObject *
+g_app_lookup_gconf_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GAppLookupGConfClass *klass;
+ GObjectClass *parent_class;
+
+ object = NULL;
+
+ /* Invoke parent constructor. */
+ klass = G_APP_LOOKUP_GCONF_CLASS (g_type_class_peek (G_TYPE_APP_LOOKUP_GCONF));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ return object;
+}
+
+static void
+g_app_lookup_gconf_init (GAppLookupGConf *lookup)
+{
+}
+
+static void
+g_app_lookup_gconf_class_finalize (GAppLookupGConfClass *klass)
+{
+}
+
+
+static void
+g_app_lookup_gconf_class_init (GAppLookupGConfClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructor = g_app_lookup_gconf_constructor;
+ gobject_class->finalize = g_app_lookup_gconf_finalize;
+}
+
+#define GCONF_PATH_PREFIX "/desktop/gnome/url-handlers/"
+
+static GAppInfo *
+get_default_for_uri_scheme (GDesktopAppInfoLookup *lookup,
+ const char *uri_scheme)
+{
+ GAppInfo *appinfo;
+ GConfClient *client;
+ char *command_key, *enabled_key, *terminal_key, *command;
+ gboolean enabled, needs_terminal;
+ GAppInfoCreateFlags flags;
+
+ appinfo = NULL;
+
+ client = gconf_client_get_default ();
+
+ command_key = g_strconcat (GCONF_PATH_PREFIX,
+ uri_scheme,
+ "/command",
+ NULL);
+ command = gconf_client_get_string (client,
+ command_key,
+ NULL);
+ g_free (command_key);
+ if (command)
+ {
+ enabled_key = g_strconcat (GCONF_PATH_PREFIX,
+ uri_scheme,
+ "/enabled",
+ NULL);
+ enabled = gconf_client_get_bool (client,
+ enabled_key,
+ NULL);
+ g_free (enabled_key);
+
+ terminal_key = g_strconcat (GCONF_PATH_PREFIX,
+ uri_scheme,
+ "/needs_terminal",
+ NULL);
+ needs_terminal = gconf_client_get_bool (client,
+ terminal_key,
+ NULL);
+ g_free (terminal_key);
+
+ if (enabled)
+ {
+ if (g_str_has_suffix (command, "\"%s\"") ||
+ g_str_has_suffix (command, "\'%s\'"))
+ command[strlen (command) - 4] = 0;
+ else if (g_str_has_suffix (command, "%s"))
+ command[strlen (command) - 2] = 0;
+
+ flags = G_APP_INFO_CREATE_SUPPORTS_URIS;
+ if (needs_terminal)
+ flags |= G_APP_INFO_CREATE_NEEDS_TERMINAL;
+ appinfo = g_app_info_create_from_commandline (command,
+ NULL,
+ flags,
+ NULL);
+ }
+ }
+
+ g_object_unref (client);
+ g_free (command);
+
+ return appinfo;
+}
+
+static void
+lookup_iface_init (GDesktopAppInfoLookupIface *iface)
+{
+ iface->get_default_for_uri_scheme = get_default_for_uri_scheme;
+}
+
+void
+g_app_lookup_gconf_register (GIOModule *module)
+{
+ g_app_lookup_gconf_register_type (G_TYPE_MODULE (module));
+ g_io_extension_point_implement (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME,
+ G_TYPE_APP_LOOKUP_GCONF,
+ "gconf",
+ 10);
+}
diff --git a/trunk/gconf/gapplookupgconf.h b/trunk/gconf/gapplookupgconf.h
new file mode 100644
index 00000000..a268415e
--- /dev/null
+++ b/trunk/gconf/gapplookupgconf.h
@@ -0,0 +1,51 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_APP_LOOKUP_GCONF_H__
+#define __G_APP_LOOKUP_GCONF_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+
+G_BEGIN_DECLS
+
+#define G_TYPE_APP_LOOKUP_GCONF (g_app_lookup_gconf_get_type ())
+#define G_APP_LOOKUP_GCONF(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_APP_LOOKUP_GCONF, GAppLookupGConf))
+#define G_APP_LOOKUP_GCONF_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_APP_LOOKUP_GCONF, GAppLookupGConfClass))
+#define G_IS_APP_LOOKUP_GCONF(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_APP_LOOKUP_GCONF))
+#define G_IS_APP_LOOKUP_GCONF_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_APP_LOOKUP_GCONF))
+
+typedef struct _GAppLookupGConf GAppLookupGConf;
+typedef struct _GAppLookupGConfClass GAppLookupGConfClass;
+
+struct _GAppLookupGConfClass {
+ GObjectClass parent_class;
+};
+
+GType g_app_lookup_gconf_get_type (void) G_GNUC_CONST;
+void g_app_lookup_gconf_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* __G_APP_LOOKUP_GCONF_H__ */
diff --git a/trunk/gconf/gconf-module.c b/trunk/gconf/gconf-module.c
new file mode 100644
index 00000000..113073f4
--- /dev/null
+++ b/trunk/gconf/gconf-module.c
@@ -0,0 +1,45 @@
+
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include "gapplookupgconf.h"
+
+void
+g_io_module_load (GIOModule *module)
+{
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ g_app_lookup_gconf_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/trunk/monitor/Makefile.am b/trunk/monitor/Makefile.am
new file mode 100644
index 00000000..d4197d52
--- /dev/null
+++ b/trunk/monitor/Makefile.am
@@ -0,0 +1,10 @@
+
+SUBDIRS = proxy
+
+if USE_HAL
+SUBDIRS += hal
+endif
+
+if USE_GPHOTO2
+SUBDIRS += gphoto2
+endif
diff --git a/trunk/monitor/gphoto2/Makefile.am b/trunk/monitor/gphoto2/Makefile.am
new file mode 100644
index 00000000..bbb54bc9
--- /dev/null
+++ b/trunk/monitor/gphoto2/Makefile.am
@@ -0,0 +1,62 @@
+
+NULL =
+
+libexec_PROGRAMS = gvfs-gphoto2-volume-monitor
+
+BUILT_SOURCES = \
+ hal-marshal.h hal-marshal.c
+
+hal-marshal.h: hal-marshal.list
+ glib-genmarshal $< --prefix=hal_marshal --header > $@
+
+hal-marshal.c: hal-marshal.list
+ echo "#include \"hal-marshal.h\"" > $@ && glib-genmarshal $< --prefix=hal_marshal --body >> $@
+
+
+gvfs_gphoto2_volume_monitor_SOURCES = \
+ hal-utils.c hal-utils.h \
+ hal-marshal.c hal-marshal.h \
+ hal-device.c hal-device.h \
+ hal-pool.c hal-pool.h \
+ gphoto2-volume-monitor-daemon.c \
+ ggphoto2volume.c ggphoto2volume.h \
+ ggphoto2volumemonitor.c ggphoto2volumemonitor.h \
+ $(NULL)
+
+gvfs_gphoto2_volume_monitor_CFLAGS = \
+ -DG_LOG_DOMAIN=\"GVFS-GPhoto2\" \
+ -I$(top_srcdir)/common \
+ -I$(top_srcdir)/monitor/proxy \
+ $(GLIB_CFLAGS) \
+ $(HAL_CFLAGS) \
+ $(GPHOTO2_CFLAGS) \
+ -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+gvfs_gphoto2_volume_monitor_LDFLAGS = \
+ $(NULL)
+
+gvfs_gphoto2_volume_monitor_LDADD = \
+ $(GLIB_LIBS) \
+ $(HAL_LIBS) \
+ $(GPHOTO2_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \
+ $(NULL)
+
+remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors
+remote_volume_monitors_DATA = gphoto2.monitor
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gtk.Private.GPhoto2VolumeMonitor.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+clean-local:
+ rm -f *~ *.loT $(BUILT_SOURCES) $(service_DATA)
+
+EXTRA_DIST = hal-marshal.list $(service_in_files) gphoto2.monitor
diff --git a/trunk/monitor/gphoto2/ggphoto2volume.c b/trunk/monitor/gphoto2/ggphoto2volume.c
new file mode 100644
index 00000000..1ddbee1f
--- /dev/null
+++ b/trunk/monitor/gphoto2/ggphoto2volume.c
@@ -0,0 +1,512 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "ggphoto2volume.h"
+
+#include "hal-utils.h"
+
+/* Protects all fields of GHalDrive that can change */
+G_LOCK_DEFINE_STATIC(gphoto2_volume);
+
+struct _GGPhoto2Volume {
+ GObject parent;
+
+ GVolumeMonitor *volume_monitor; /* owned by volume monitor */
+
+ char *device_path;
+ HalDevice *device;
+ HalDevice *drive_device;
+
+ GFile *activation_root;
+
+ char *name;
+ char *icon;
+};
+
+static void g_gphoto2_volume_volume_iface_init (GVolumeIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GGPhoto2Volume, g_gphoto2_volume, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
+ g_gphoto2_volume_volume_iface_init))
+
+static void
+g_gphoto2_volume_finalize (GObject *object)
+{
+ GGPhoto2Volume *volume;
+
+ volume = G_GPHOTO2_VOLUME (object);
+
+ if (volume->device != NULL)
+ g_object_unref (volume->device);
+
+ if (volume->activation_root != NULL)
+ g_object_unref (volume->activation_root);
+
+ if (volume->volume_monitor != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (volume->volume_monitor), (gpointer) &(volume->volume_monitor));
+
+ g_free (volume->name);
+ g_free (volume->icon);
+
+ if (G_OBJECT_CLASS (g_gphoto2_volume_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_gphoto2_volume_parent_class)->finalize) (object);
+}
+
+static void
+g_gphoto2_volume_class_init (GGPhoto2VolumeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_gphoto2_volume_finalize;
+}
+
+static void
+g_gphoto2_volume_init (GGPhoto2Volume *gphoto2_volume)
+{
+}
+
+static gboolean
+changed_in_idle (gpointer data)
+{
+ GGPhoto2Volume *volume = data;
+
+ g_signal_emit_by_name (volume, "changed");
+ if (volume->volume_monitor != NULL)
+ g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+ g_object_unref (volume);
+
+ return FALSE;
+}
+
+static char **
+dupv_and_uniqify (char **str_array)
+{
+ int n, m, o;
+ int len;
+ char **result;
+
+ result = g_strdupv (str_array);
+ len = g_strv_length (result);
+
+ for (n = 0; n < len; n++)
+ {
+ char *s = result[n];
+ for (m = n + 1; m < len; m++)
+ {
+ char *p = result[m];
+ if (strcmp (s, p) == 0)
+ {
+ for (o = m + 1; o < len; o++)
+ result[o - 1] = result[o];
+ len--;
+ result[len] = NULL;
+ m--;
+ }
+ }
+ }
+
+ return result;
+}
+
+static void
+do_update_from_hal_for_camera (GGPhoto2Volume *v)
+{
+ const char *vendor;
+ const char *product;
+ const char *icon_from_hal;
+ const char *name_from_hal;
+ gboolean is_audio_player;
+
+ vendor = hal_device_get_property_string (v->drive_device, "usb_device.vendor");
+ product = hal_device_get_property_string (v->drive_device, "usb_device.product");
+ icon_from_hal = hal_device_get_property_string (v->device, "info.desktop.icon");
+ name_from_hal = hal_device_get_property_string (v->device, "info.desktop.name");
+
+ is_audio_player = hal_device_has_capability (v->device, "portable_audio_player");
+
+ v->name = NULL;
+ if (strlen (name_from_hal) > 0)
+ v->name = g_strdup (name_from_hal);
+ else if (vendor == NULL)
+ {
+ if (product != NULL)
+ v->name = g_strdup (product);
+ }
+ else
+ {
+ if (product != NULL)
+ v->name = g_strdup_printf ("%s %s", vendor, product);
+ else
+ {
+ if (is_audio_player)
+ {
+ /* Translators: %s is the device vendor */
+ v->name = g_strdup_printf (_("%s Audio Player"), vendor);
+ }
+ else
+ {
+ /* Translators: %s is the device vendor */
+ v->name = g_strdup_printf (_("%s Camera"), vendor);
+ }
+ }
+ }
+ if (v->name == NULL)
+ {
+ if (is_audio_player)
+ v->name = g_strdup (_("Audio Player"));
+ else
+ v->name = g_strdup (_("Camera"));
+ }
+
+ if (strlen (icon_from_hal) > 0)
+ v->icon = g_strdup (icon_from_hal);
+ else if (is_audio_player)
+ v->icon = g_strdup ("multimedia-player");
+ else
+ v->icon = g_strdup ("camera-photo");
+
+ g_object_set_data_full (G_OBJECT (v),
+ "hal-storage-device-capabilities",
+ dupv_and_uniqify (hal_device_get_property_strlist (v->device, "info.capabilities")),
+ (GDestroyNotify) g_strfreev);
+}
+
+static void
+update_from_hal (GGPhoto2Volume *mv, gboolean emit_changed)
+{
+ char *old_name;
+ char *old_icon;
+
+ G_LOCK (gphoto2_volume);
+
+ old_name = g_strdup (mv->name);
+ old_icon = g_strdup (mv->icon);
+
+ g_free (mv->name);
+ g_free (mv->icon);
+
+ do_update_from_hal_for_camera (mv);
+
+ if (emit_changed)
+ {
+ if (old_name == NULL ||
+ old_icon == NULL ||
+ strcmp (old_name, mv->name) != 0 ||
+ strcmp (old_icon, mv->icon) != 0)
+ g_idle_add (changed_in_idle, g_object_ref (mv));
+ }
+ g_free (old_name);
+ g_free (old_icon);
+
+ G_UNLOCK (gphoto2_volume);
+}
+
+static void
+hal_changed (HalDevice *device, const char *key, gpointer user_data)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (user_data);
+
+ /*g_warning ("hal modifying %s (property %s changed)", gphoto2_volume->device_path, key);*/
+ update_from_hal (gphoto2_volume, TRUE);
+}
+
+GGPhoto2Volume *
+g_gphoto2_volume_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool,
+ GFile *activation_root)
+{
+ GGPhoto2Volume *volume;
+ HalDevice *drive_device;
+ const char *storage_udi;
+ const char *device_path;
+
+ g_return_val_if_fail (volume_monitor != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
+ g_return_val_if_fail (pool != NULL, NULL);
+ g_return_val_if_fail (activation_root != NULL, NULL);
+
+ if (!(hal_device_has_capability (device, "camera") ||
+ (hal_device_has_capability (device, "portable_audio_player") &&
+ hal_device_get_property_bool (device, "camera.libgphoto2.support"))))
+ return NULL;
+
+ /* OK, so we abuse storage_udi and drive_device for the USB main
+ * device that holds this interface...
+ */
+ storage_udi = hal_device_get_property_string (device, "info.parent");
+ if (storage_udi == NULL)
+ return NULL;
+
+ drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+ if (drive_device == NULL)
+ return NULL;
+
+ /* TODO: other OS'es? Will address this with DK aka HAL 2.0 */
+ device_path = hal_device_get_property_string (drive_device, "linux.device_file");
+ if (strlen (device_path) == 0)
+ device_path = NULL;
+
+ volume = g_object_new (G_TYPE_GPHOTO2_VOLUME, NULL);
+ volume->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor));
+ volume->device_path = g_strdup (device_path);
+ volume->device = g_object_ref (device);
+ volume->drive_device = g_object_ref (drive_device);
+ volume->activation_root = g_object_ref (activation_root);
+
+ g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, volume, 0);
+ g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, volume, 0);
+
+ update_from_hal (volume, FALSE);
+
+ return volume;
+}
+
+void
+g_gphoto2_volume_removed (GGPhoto2Volume *volume)
+{
+ ;
+}
+
+static GIcon *
+g_gphoto2_volume_get_icon (GVolume *volume)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ GIcon *icon;
+
+ G_LOCK (gphoto2_volume);
+ icon = g_themed_icon_new (gphoto2_volume->icon);
+ G_UNLOCK (gphoto2_volume);
+ return icon;
+}
+
+static char *
+g_gphoto2_volume_get_name (GVolume *volume)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ char *name;
+
+ G_LOCK (gphoto2_volume);
+ name = g_strdup (gphoto2_volume->name);
+ G_UNLOCK (gphoto2_volume);
+
+ return name;
+}
+
+static char *
+g_gphoto2_volume_get_uuid (GVolume *volume)
+{
+ return NULL;
+}
+
+static gboolean
+g_gphoto2_volume_can_mount (GVolume *volume)
+{
+ return TRUE;
+}
+
+static gboolean
+g_gphoto2_volume_can_eject (GVolume *volume)
+{
+ return FALSE;
+}
+
+static gboolean
+g_gphoto2_volume_should_automount (GVolume *volume)
+{
+ return TRUE;
+}
+
+static GDrive *
+g_gphoto2_volume_get_drive (GVolume *volume)
+{
+ return NULL;
+}
+
+static GMount *
+g_gphoto2_volume_get_mount (GVolume *volume)
+{
+ return NULL;
+}
+
+gboolean
+g_gphoto2_volume_has_udi (GGPhoto2Volume *volume,
+ const char *udi)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (gphoto2_volume);
+ res = FALSE;
+ if (gphoto2_volume->device != NULL)
+ res = strcmp (hal_device_get_udi (gphoto2_volume->device), udi) == 0;
+ G_UNLOCK (gphoto2_volume);
+ return res;
+}
+
+typedef struct
+{
+ GGPhoto2Volume *enclosing_volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} ActivationMountOp;
+
+static void
+mount_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ActivationMountOp *data = user_data;
+ data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data);
+ g_free (data);
+}
+
+static void
+g_gphoto2_volume_mount (GVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ ActivationMountOp *data;
+
+ /*g_warning ("gphoto2_volume_mount (can_mount=%d foreign=%p device_path=%s)",
+ g_gphoto2_volume_can_mount (volume),
+ gphoto2_volume->activation_root,
+ gphoto2_volume->device_path);*/
+
+ G_LOCK (gphoto2_volume);
+
+ data = g_new0 (ActivationMountOp, 1);
+ data->enclosing_volume = gphoto2_volume;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ g_file_mount_enclosing_volume (gphoto2_volume->activation_root,
+ 0,
+ mount_operation,
+ cancellable,
+ mount_callback,
+ data);
+
+ G_UNLOCK (gphoto2_volume);
+}
+
+static gboolean
+g_gphoto2_volume_mount_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (gphoto2_volume);
+ res = g_file_mount_enclosing_volume_finish (gphoto2_volume->activation_root, result, error);
+ G_UNLOCK (gphoto2_volume);
+
+ return res;
+}
+
+static char *
+g_gphoto2_volume_get_identifier (GVolume *volume,
+ const char *kind)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ char *id;
+
+ G_LOCK (gphoto2_volume);
+ id = NULL;
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0)
+ id = g_strdup (hal_device_get_udi (gphoto2_volume->device));
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+ id = g_strdup (gphoto2_volume->device_path);
+ G_UNLOCK (gphoto2_volume);
+
+ return id;
+}
+
+static char **
+g_gphoto2_volume_enumerate_identifiers (GVolume *volume)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+ GPtrArray *res;
+
+ G_LOCK (gphoto2_volume);
+
+ res = g_ptr_array_new ();
+
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI));
+
+ if (gphoto2_volume->device_path && *gphoto2_volume->device_path != 0)
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE));
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ G_UNLOCK (gphoto2_volume);
+
+ return (char **)g_ptr_array_free (res, FALSE);
+}
+
+static GFile *
+g_gphoto2_volume_get_activation_root (GVolume *volume)
+{
+ GGPhoto2Volume *gphoto2_volume = G_GPHOTO2_VOLUME (volume);
+
+ return g_object_ref (gphoto2_volume->activation_root);
+}
+
+static void
+g_gphoto2_volume_volume_iface_init (GVolumeIface *iface)
+{
+ iface->get_name = g_gphoto2_volume_get_name;
+ iface->get_icon = g_gphoto2_volume_get_icon;
+ iface->get_uuid = g_gphoto2_volume_get_uuid;
+ iface->get_drive = g_gphoto2_volume_get_drive;
+ iface->get_mount = g_gphoto2_volume_get_mount;
+ iface->can_mount = g_gphoto2_volume_can_mount;
+ iface->can_eject = g_gphoto2_volume_can_eject;
+ iface->should_automount = g_gphoto2_volume_should_automount;
+ iface->mount_fn = g_gphoto2_volume_mount;
+ iface->mount_finish = g_gphoto2_volume_mount_finish;
+ iface->eject = NULL;
+ iface->eject_finish = NULL;
+ iface->get_identifier = g_gphoto2_volume_get_identifier;
+ iface->enumerate_identifiers = g_gphoto2_volume_enumerate_identifiers;
+ iface->get_activation_root = g_gphoto2_volume_get_activation_root;
+}
diff --git a/trunk/monitor/gphoto2/ggphoto2volume.h b/trunk/monitor/gphoto2/ggphoto2volume.h
new file mode 100644
index 00000000..a7a4131e
--- /dev/null
+++ b/trunk/monitor/gphoto2/ggphoto2volume.h
@@ -0,0 +1,60 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_GPHOTO2_VOLUME_H__
+#define __G_GPHOTO2_VOLUME_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "hal-pool.h"
+#include "ggphoto2volumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_GPHOTO2_VOLUME (g_gphoto2_volume_get_type ())
+#define G_GPHOTO2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_GPHOTO2_VOLUME, GGPhoto2Volume))
+#define G_GPHOTO2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_GPHOTO2_VOLUME, GGPhoto2VolumeClass))
+#define G_IS_GPHOTO2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_GPHOTO2_VOLUME))
+#define G_IS_GPHOTO2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_GPHOTO2_VOLUME))
+
+typedef struct _GGPhoto2VolumeClass GGPhoto2VolumeClass;
+
+struct _GGPhoto2VolumeClass {
+ GObjectClass parent_class;
+};
+
+GType g_gphoto2_volume_get_type (void) G_GNUC_CONST;
+
+GGPhoto2Volume *g_gphoto2_volume_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool,
+ GFile *activation_root);
+
+gboolean g_gphoto2_volume_has_udi (GGPhoto2Volume *volume,
+ const char *udi);
+
+void g_gphoto2_volume_removed (GGPhoto2Volume *volume);
+
+G_END_DECLS
+
+#endif /* __G_GPHOTO2_VOLUME_H__ */
diff --git a/trunk/monitor/gphoto2/ggphoto2volumemonitor.c b/trunk/monitor/gphoto2/ggphoto2volumemonitor.c
new file mode 100644
index 00000000..89a7f0b1
--- /dev/null
+++ b/trunk/monitor/gphoto2/ggphoto2volumemonitor.c
@@ -0,0 +1,611 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gphoto2.h>
+#include <gio/gio.h>
+
+#include "ggphoto2volumemonitor.h"
+#include "ggphoto2volume.h"
+
+#include "hal-pool.h"
+
+G_LOCK_DEFINE_STATIC(hal_vm);
+
+static GGPhoto2VolumeMonitor *the_volume_monitor = NULL;
+static HalPool *pool = NULL;
+
+struct _GGPhoto2VolumeMonitor {
+ GNativeVolumeMonitor parent;
+
+ GUnixMountMonitor *mount_monitor;
+
+ HalPool *pool;
+
+ GList *last_camera_devices;
+
+ GList *camera_volumes;
+};
+
+static void hal_changed (HalPool *pool,
+ HalDevice *device,
+ gpointer user_data);
+
+static void update_all (GGPhoto2VolumeMonitor *monitor,
+ gboolean emit_changes);
+
+static void update_cameras (GGPhoto2VolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes);
+
+
+G_DEFINE_TYPE (GGPhoto2VolumeMonitor, g_gphoto2_volume_monitor, G_TYPE_VOLUME_MONITOR)
+
+static void
+list_free (GList *objects)
+{
+ g_list_foreach (objects, (GFunc)g_object_unref, NULL);
+ g_list_free (objects);
+}
+
+static HalPool *
+get_hal_pool (void)
+{
+ char *cap_only[] = {"camera", "portable_audio_player", "usb_device", NULL};
+
+ if (pool == NULL)
+ pool = hal_pool_new (cap_only);
+
+ return pool;
+}
+
+static void
+g_gphoto2_volume_monitor_dispose (GObject *object)
+{
+ GGPhoto2VolumeMonitor *monitor;
+
+ monitor = G_GPHOTO2_VOLUME_MONITOR (object);
+
+ G_LOCK (hal_vm);
+ the_volume_monitor = NULL;
+ G_UNLOCK (hal_vm);
+
+ if (G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->dispose)
+ (*G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->dispose) (object);
+}
+
+static void
+g_gphoto2_volume_monitor_finalize (GObject *object)
+{
+ GGPhoto2VolumeMonitor *monitor;
+
+ monitor = G_GPHOTO2_VOLUME_MONITOR (object);
+
+ g_signal_handlers_disconnect_by_func (monitor->pool, hal_changed, monitor);
+
+ g_object_unref (monitor->pool);
+
+ list_free (monitor->last_camera_devices);
+ list_free (monitor->camera_volumes);
+
+ if (G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_gphoto2_volume_monitor_parent_class)->finalize) (object);
+}
+
+static GList *
+get_mounts (GVolumeMonitor *volume_monitor)
+{
+ return NULL;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+ GGPhoto2VolumeMonitor *monitor;
+ GList *l;
+
+ monitor = G_GPHOTO2_VOLUME_MONITOR (volume_monitor);
+
+ G_LOCK (hal_vm);
+
+ l = g_list_copy (monitor->camera_volumes);
+ g_list_foreach (l, (GFunc)g_object_ref, NULL);
+
+ G_UNLOCK (hal_vm);
+
+ return l;
+}
+
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
+{
+ return NULL;
+}
+
+static GVolume *
+get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ return NULL;
+}
+
+static GMount *
+get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ return NULL;
+}
+
+static void
+hal_changed (HalPool *pool,
+ HalDevice *device,
+ gpointer user_data)
+{
+ GGPhoto2VolumeMonitor *monitor = G_GPHOTO2_VOLUME_MONITOR (user_data);
+
+ /*g_warning ("hal changed");*/
+
+ update_all (monitor, TRUE);
+}
+
+static GObject *
+g_gphoto2_volume_monitor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GGPhoto2VolumeMonitor *monitor;
+ GGPhoto2VolumeMonitorClass *klass;
+ GObjectClass *parent_class;
+
+ G_LOCK (hal_vm);
+ if (the_volume_monitor != NULL)
+ {
+ object = g_object_ref (the_volume_monitor);
+ G_UNLOCK (hal_vm);
+ return object;
+ }
+ G_UNLOCK (hal_vm);
+
+ /*g_warning ("creating hal vm");*/
+
+ object = NULL;
+
+ /* Invoke parent constructor. */
+ klass = G_GPHOTO2_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_GPHOTO2_VOLUME_MONITOR));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ monitor = G_GPHOTO2_VOLUME_MONITOR (object);
+ monitor->pool = g_object_ref (get_hal_pool ());
+
+ g_signal_connect (monitor->pool,
+ "device_added", G_CALLBACK (hal_changed),
+ monitor);
+
+ g_signal_connect (monitor->pool,
+ "device_removed", G_CALLBACK (hal_changed),
+ monitor);
+
+ update_all (monitor, FALSE);
+
+ G_LOCK (hal_vm);
+ the_volume_monitor = monitor;
+ G_UNLOCK (hal_vm);
+
+ return object;
+}
+
+static void
+g_gphoto2_volume_monitor_init (GGPhoto2VolumeMonitor *monitor)
+{
+}
+
+static gboolean
+is_supported (void)
+{
+ return get_hal_pool() != NULL;
+}
+
+static void
+g_gphoto2_volume_monitor_class_init (GGPhoto2VolumeMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+
+ gobject_class->constructor = g_gphoto2_volume_monitor_constructor;
+ gobject_class->finalize = g_gphoto2_volume_monitor_finalize;
+ gobject_class->dispose = g_gphoto2_volume_monitor_dispose;
+
+ monitor_class->get_mounts = get_mounts;
+ monitor_class->get_volumes = get_volumes;
+ monitor_class->get_connected_drives = get_connected_drives;
+ monitor_class->get_volume_for_uuid = get_volume_for_uuid;
+ monitor_class->get_mount_for_uuid = get_mount_for_uuid;
+ monitor_class->is_supported = is_supported;
+}
+
+/**
+ * g_gphoto2_volume_monitor_new:
+ *
+ * Returns: a new #GVolumeMonitor.
+ **/
+GVolumeMonitor *
+g_gphoto2_volume_monitor_new (void)
+{
+ GGPhoto2VolumeMonitor *monitor;
+
+ monitor = g_object_new (G_TYPE_GPHOTO2_VOLUME_MONITOR, NULL);
+
+ return G_VOLUME_MONITOR (monitor);
+}
+
+static void
+diff_sorted_lists (GList *list1,
+ GList *list2,
+ GCompareFunc compare,
+ GList **added,
+ GList **removed)
+{
+ int order;
+
+ *added = *removed = NULL;
+
+ while (list1 != NULL &&
+ list2 != NULL)
+ {
+ order = (*compare) (list1->data, list2->data);
+ if (order < 0)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ else if (order > 0)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+ else
+ { /* same item */
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+ }
+
+ while (list1 != NULL)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ while (list2 != NULL)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+}
+
+static GGPhoto2Volume *
+find_camera_volume_by_udi (GGPhoto2VolumeMonitor *monitor, const char *udi)
+{
+ GList *l;
+
+ for (l = monitor->camera_volumes; l != NULL; l = l->next)
+ {
+ GGPhoto2Volume *volume = l->data;
+
+ if (g_gphoto2_volume_has_udi (volume, udi))
+ return volume;
+ }
+
+ return NULL;
+}
+
+static gint
+hal_device_compare (HalDevice *a, HalDevice *b)
+{
+ return strcmp (hal_device_get_udi (a), hal_device_get_udi (b));
+}
+
+static void
+list_emit (GGPhoto2VolumeMonitor *monitor,
+ const char *monitor_signal,
+ const char *object_signal,
+ GList *objects)
+{
+ GList *l;
+
+ for (l = objects; l != NULL; l = l->next)
+ {
+ g_signal_emit_by_name (monitor, monitor_signal, l->data);
+ if (object_signal)
+ g_signal_emit_by_name (l->data, object_signal);
+ }
+}
+
+typedef struct {
+ GGPhoto2VolumeMonitor *monitor;
+ GList *added_volumes, *removed_volumes;
+} ChangedLists;
+
+
+static gboolean
+emit_lists_in_idle (gpointer data)
+{
+ ChangedLists *lists = data;
+
+ list_emit (lists->monitor,
+ "volume_removed", "removed",
+ lists->removed_volumes);
+ list_emit (lists->monitor,
+ "volume_added", NULL,
+ lists->added_volumes);
+
+ list_free (lists->removed_volumes);
+ list_free (lists->added_volumes);
+ g_object_unref (lists->monitor);
+ g_free (lists);
+
+ return FALSE;
+}
+
+/* Must be called from idle if emit_changes, with no locks held */
+static void
+update_all (GGPhoto2VolumeMonitor *monitor,
+ gboolean emit_changes)
+{
+ ChangedLists *lists;
+ GList *added_volumes, *removed_volumes;
+
+ added_volumes = NULL;
+ removed_volumes = NULL;
+
+ G_LOCK (hal_vm);
+ update_cameras (monitor, &added_volumes, &removed_volumes);
+ G_UNLOCK (hal_vm);
+
+ if (emit_changes)
+ {
+ lists = g_new0 (ChangedLists, 1);
+ lists->monitor = g_object_ref (monitor);
+ lists->added_volumes = added_volumes;
+ lists->removed_volumes = removed_volumes;
+
+ g_idle_add (emit_lists_in_idle, lists);
+ }
+ else
+ {
+ list_free (removed_volumes);
+ list_free (added_volumes);
+ }
+}
+
+static GList *
+get_stores_for_camera (int bus_num, int device_num)
+{
+ GList *l;
+ CameraStorageInformation *storage_info;
+ GPContext *context;
+ GPPortInfo info;
+ GPPortInfoList *il;
+ int num_storage_info, n;
+ Camera *camera;
+ char *port;
+ guint i;
+
+ il = NULL;
+ camera = NULL;
+ context = NULL;
+ l = NULL;
+ port = g_strdup_printf ("usb:%d,%d", bus_num, device_num);
+
+ /* Connect to the camera */
+ context = gp_context_new ();
+ if (gp_camera_new (&camera) != 0)
+ goto out;
+ if (gp_port_info_list_new (&il) != 0)
+ goto out;
+ if (gp_port_info_list_load (il) != 0)
+ goto out;
+ n = gp_port_info_list_lookup_path (il, port);
+ if (n == GP_ERROR_UNKNOWN_PORT)
+ goto out;
+ if (gp_port_info_list_get_info (il, n, &info) != 0)
+ goto out;
+ if (gp_camera_set_port_info (camera, info) != 0)
+ goto out;
+ gp_port_info_list_free (il);
+ il = NULL;
+ if (gp_camera_init (camera, context) != 0)
+ goto out;
+
+ /* Get information about the storage heads */
+ if (gp_camera_get_storageinfo (camera, &storage_info, &num_storage_info, context) != 0)
+ goto out;
+
+ /* Append the data to the list */
+ for (i = 0; i < num_storage_info; i++)
+ {
+ /* Ignore storage with no capacity (see bug 570888) */
+ if ((storage_info[i].fields & GP_STORAGEINFO_MAXCAPACITY) &&
+ storage_info[i].capacitykbytes == 0)
+ continue;
+ l = g_list_prepend (l, g_strdup (storage_info[i].basedir));
+ }
+
+out:
+ /* Clean up */
+ if (il != NULL)
+ gp_port_info_list_free (il);
+ if (context != NULL)
+ gp_context_unref (context);
+ if (camera != NULL)
+ gp_camera_unref (camera);
+
+ g_free (port);
+
+ return l;
+}
+
+static void
+update_cameras (GGPhoto2VolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes)
+{
+ GList *new_camera_devices;
+ GList *new_mtp_devices;
+ GList *removed, *added;
+ GList *l, *ll;
+ GGPhoto2Volume *volume;
+ const char *udi;
+
+ new_mtp_devices = hal_pool_find_by_capability (monitor->pool, "portable_audio_player");
+ for (l = new_mtp_devices; l != NULL; l = ll)
+ {
+ HalDevice *d = l->data;
+ ll = l->next;
+ if (! hal_device_get_property_bool (d, "camera.libgphoto2.support"))
+ {
+ /*g_warning ("ignoring %s", hal_device_get_udi (d));*/
+ /* filter out everything that isn't supported by libgphoto2 */
+ new_mtp_devices = g_list_delete_link (new_mtp_devices, l);
+ }
+ }
+
+ new_camera_devices = hal_pool_find_by_capability (monitor->pool, "camera");
+ new_camera_devices = g_list_concat (new_camera_devices, new_mtp_devices);
+ for (l = new_camera_devices; l != NULL; l = ll)
+ {
+ HalDevice *d = l->data;
+ ll = l->next;
+ /*g_warning ("got %s", hal_device_get_udi (d));*/
+ if (! hal_device_get_property_bool (d, "camera.libgphoto2.support"))
+ {
+ /*g_warning ("ignoring %s", hal_device_get_udi (d));*/
+ /* filter out everything that isn't supported by libgphoto2 */
+ new_camera_devices = g_list_delete_link (new_camera_devices, l);
+ }
+ }
+ g_list_foreach (new_camera_devices, (GFunc) g_object_ref, NULL);
+
+ new_camera_devices = g_list_sort (new_camera_devices, (GCompareFunc) hal_device_compare);
+ diff_sorted_lists (monitor->last_camera_devices,
+ new_camera_devices, (GCompareFunc) hal_device_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ udi = hal_device_get_udi (d);
+ /*g_warning ("camera removing %s", udi);*/
+
+ volume = find_camera_volume_by_udi (monitor, udi);
+ if (volume != NULL)
+ {
+ g_gphoto2_volume_removed (volume);
+ monitor->camera_volumes = g_list_remove (monitor->camera_volumes, volume);
+ *removed_volumes = g_list_prepend (*removed_volumes, volume);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+ int usb_bus_num;
+ int usb_device_num;
+ gboolean found;
+ GList *store_heads, *l;
+ guint num_store_heads;
+
+ /* Look for the device in the added volumes, so as
+ * not to add devices that are both audio players, and cameras */
+ found = FALSE;
+ for (ll = *added_volumes; ll; ll = ll->next)
+ {
+ if (g_gphoto2_volume_has_udi (ll->data, hal_device_get_udi (d)) != FALSE)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ usb_bus_num = hal_device_get_property_int (d, "usb.bus_number");
+ usb_device_num = hal_device_get_property_int (d, "usb.linux.device_number");
+
+ store_heads = get_stores_for_camera (usb_bus_num, usb_device_num);
+ num_store_heads = g_list_length (store_heads);
+ for (l = store_heads ; l != NULL; l = l->next)
+ {
+ char *store_path = (char *) l->data;
+ GFile *activation_mount_root;
+ gchar *uri;
+
+ /* If we only have a single store, don't use the store name at all. The backend automatically
+ * prepend the storename; this is to work around bugs with devices (like the iPhone) for which
+ * the store name changes every time the camera is initialized (e.g. mounted).
+ */
+ if (num_store_heads == 1)
+ {
+ uri = g_strdup_printf ("gphoto2://[usb:%03d,%03d]", usb_bus_num, usb_device_num);
+ }
+ else
+ {
+ uri = g_strdup_printf ("gphoto2://[usb:%03d,%03d]/%s", usb_bus_num, usb_device_num,
+ store_path[0] == '/' ? store_path + 1 : store_path);
+ }
+ activation_mount_root = g_file_new_for_uri (uri);
+ g_free (uri);
+
+ udi = hal_device_get_udi (d);
+ volume = g_gphoto2_volume_new (G_VOLUME_MONITOR (monitor),
+ d,
+ monitor->pool,
+ activation_mount_root);
+ if (volume != NULL)
+ {
+ monitor->camera_volumes = g_list_prepend (monitor->camera_volumes, volume);
+ *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+ }
+
+ if (activation_mount_root != NULL)
+ g_object_unref (activation_mount_root);
+ }
+ g_list_foreach (store_heads, (GFunc) g_free, NULL);
+ g_list_free (store_heads);
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+ list_free (monitor->last_camera_devices);
+ monitor->last_camera_devices = new_camera_devices;
+}
diff --git a/trunk/monitor/gphoto2/ggphoto2volumemonitor.h b/trunk/monitor/gphoto2/ggphoto2volumemonitor.h
new file mode 100644
index 00000000..fcb74fef
--- /dev/null
+++ b/trunk/monitor/gphoto2/ggphoto2volumemonitor.h
@@ -0,0 +1,54 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_GPHOTO2_VOLUME_MONITOR_H__
+#define __G_GPHOTO2_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_GPHOTO2_VOLUME_MONITOR (g_gphoto2_volume_monitor_get_type ())
+#define G_GPHOTO2_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_GPHOTO2_VOLUME_MONITOR, GGPhoto2VolumeMonitor))
+#define G_GPHOTO2_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_GPHOTO2_VOLUME_MONITOR, GGPhoto2VolumeMonitorClass))
+#define G_IS_GPHOTO2_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_GPHOTO2_VOLUME_MONITOR))
+#define G_IS_GPHOTO2_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_GPHOTO2_VOLUME_MONITOR))
+
+typedef struct _GGPhoto2VolumeMonitor GGPhoto2VolumeMonitor;
+typedef struct _GGPhoto2VolumeMonitorClass GGPhoto2VolumeMonitorClass;
+
+/* Forward definitions */
+typedef struct _GGPhoto2Volume GGPhoto2Volume;
+
+struct _GGPhoto2VolumeMonitorClass {
+ GVolumeMonitorClass parent_class;
+};
+
+GType g_gphoto2_volume_monitor_get_type (void) G_GNUC_CONST;
+
+GVolumeMonitor *g_gphoto2_volume_monitor_new (void);
+void g_gphoto2_volume_monitor_force_update (GGPhoto2VolumeMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __G_GPHOTO2_VOLUME_MONITOR_H__ */
diff --git a/trunk/monitor/gphoto2/gphoto2-volume-monitor-daemon.c b/trunk/monitor/gphoto2/gphoto2-volume-monitor-daemon.c
new file mode 100644
index 00000000..f4998f35
--- /dev/null
+++ b/trunk/monitor/gphoto2/gphoto2-volume-monitor-daemon.c
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include <gvfsproxyvolumemonitordaemon.h>
+
+#include "ggphoto2volumemonitor.h"
+
+int
+main (int argc, char *argv[])
+{
+ g_vfs_proxy_volume_monitor_daemon_init ();
+ return g_vfs_proxy_volume_monitor_daemon_main (argc,
+ argv,
+ "org.gtk.Private.GPhoto2VolumeMonitor",
+ G_TYPE_GPHOTO2_VOLUME_MONITOR);
+}
diff --git a/trunk/monitor/gphoto2/gphoto2.monitor b/trunk/monitor/gphoto2/gphoto2.monitor
new file mode 100644
index 00000000..e0a69852
--- /dev/null
+++ b/trunk/monitor/gphoto2/gphoto2.monitor
@@ -0,0 +1,4 @@
+[RemoteVolumeMonitor]
+Name=GProxyVolumeMonitorGPhoto2
+DBusName=org.gtk.Private.GPhoto2VolumeMonitor
+IsNative=false
diff --git a/trunk/monitor/gphoto2/hal-device.c b/trunk/monitor/gphoto2/hal-device.c
new file mode 100644
index 00000000..9f0b5bc3
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-device.c
@@ -0,0 +1,297 @@
+/* hal-device.c
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include "hal-device.h"
+#include "hal-marshal.h"
+
+struct _HalDevicePrivate
+{
+ LibHalContext *hal_ctx;
+ LibHalPropertySet *properties;
+ char *udi;
+ GTimeVal time_added;
+};
+
+enum {
+ HAL_PROPERTY_CHANGED,
+ HAL_CONDITION,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (HalDevice, hal_device, G_TYPE_OBJECT)
+
+static void
+hal_device_finalize (HalDevice *device)
+{
+ if (device->priv->properties != NULL)
+ libhal_free_property_set (device->priv->properties);
+ g_free (device->priv->udi);
+
+ if (G_OBJECT_CLASS (hal_device_parent_class)->finalize)
+ (* G_OBJECT_CLASS (hal_device_parent_class)->finalize) (G_OBJECT (device));
+}
+
+static void
+hal_device_class_init (HalDeviceClass *klass)
+{
+ GObjectClass *obj_class = (GObjectClass *) klass;
+
+ obj_class->finalize = (GObjectFinalizeFunc) hal_device_finalize;
+
+ signals[HAL_PROPERTY_CHANGED] =
+ g_signal_new ("hal_property_changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, hal_property_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ signals[HAL_CONDITION] =
+ g_signal_new ("hal_condition",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, hal_condition),
+ NULL, NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+}
+
+static void
+hal_device_init (HalDevice *device)
+{
+ device->priv = g_new0 (HalDevicePrivate, 1);
+ g_get_current_time (&(device->priv->time_added));
+}
+
+const char *
+hal_device_get_property_string (HalDevice *device, const char *key)
+{
+ const char *ret;
+
+ ret = libhal_ps_get_string (device->priv->properties, key);
+ if (ret != NULL)
+ return ret;
+
+ /* play it safe and don't make clients crash */
+ return "";
+}
+
+int
+hal_device_get_property_int (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_int32 (device->priv->properties, key);
+}
+
+double
+hal_device_get_property_double (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_double (device->priv->properties, key);
+}
+
+guint64
+hal_device_get_property_uint64 (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_uint64 (device->priv->properties, key);
+}
+
+gboolean
+hal_device_get_property_bool (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_bool (device->priv->properties, key);
+}
+
+char **
+hal_device_get_property_strlist (HalDevice *device, const char *key)
+{
+ static char * empty[1] = {NULL};
+ char **ret;
+
+ ret = (char **) libhal_ps_get_strlist (device->priv->properties, key);
+ if (ret != NULL)
+ return (char **) ret;
+
+ /* play it safe and don't make clients crash */
+ return empty;
+}
+
+gboolean
+hal_device_has_capability (HalDevice *device, const char *capability)
+{
+ int n;
+ char **caps;
+ gboolean ret;
+
+ ret = FALSE;
+ caps = hal_device_get_property_strlist (device, "info.capabilities");
+ if (caps == NULL)
+ goto out;
+
+ for (n = 0; caps[n] != NULL; n++)
+ {
+ if (g_ascii_strcasecmp (caps[n], capability) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+gboolean
+hal_device_has_interface (HalDevice *device, const char *interface)
+{
+ int n;
+ char **ifs;
+ gboolean ret;
+
+ ret = FALSE;
+ ifs = hal_device_get_property_strlist (device, "info.interfaces");
+ if (ifs == NULL)
+ goto out;
+
+ for (n = 0; ifs[n] != NULL; n++)
+ {
+ if (g_ascii_strcasecmp (ifs[n], interface) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+out:
+ return ret;
+}
+
+gboolean
+hal_device_has_property (HalDevice *device, const char *key)
+{
+ gboolean ret;
+ LibHalPropertySetIterator it;
+
+ ret = FALSE;
+ if (device->priv->properties == NULL)
+ goto out;
+
+ libhal_psi_init (&it, device->priv->properties);
+
+ while (libhal_psi_has_more (&it))
+ {
+ char *pkey = libhal_psi_get_key (&it);
+
+ if (pkey != NULL && g_ascii_strcasecmp (pkey, key) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ libhal_psi_next (&it);
+ }
+
+ out:
+ return ret;
+}
+
+
+HalDevice *
+hal_device_new_from_udi (LibHalContext *hal_ctx, const char *udi)
+{
+ HalDevice *device;
+
+ device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
+ device->priv->udi = g_strdup (udi);
+ device->priv->hal_ctx = hal_ctx;
+ device->priv->properties = libhal_device_get_all_properties (hal_ctx, udi, NULL);
+ return device;
+}
+
+HalDevice *
+hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx,
+ char *udi,
+ LibHalPropertySet *properties)
+{
+ HalDevice *device;
+
+ device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
+ device->priv->udi = g_strdup (udi);
+ device->priv->hal_ctx = hal_ctx;
+ device->priv->properties = properties;
+ return device;
+}
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key);
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail);
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key)
+{
+ LibHalPropertySet *new_props;
+
+ new_props = libhal_device_get_all_properties (device->priv->hal_ctx, device->priv->udi, NULL);
+ if (new_props != NULL)
+ {
+ libhal_free_property_set (device->priv->properties);
+ device->priv->properties = new_props;
+ g_signal_emit (device, signals[HAL_PROPERTY_CHANGED], 0, key);
+ }
+}
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail)
+{
+ g_signal_emit (device, signals[HAL_CONDITION], 0, name, detail);
+}
+
+const char *
+hal_device_get_udi (HalDevice *device)
+{
+ return device->priv->udi;
+}
+
+LibHalPropertySet *
+hal_device_get_properties (HalDevice *device)
+{
+ return device->priv->properties;
+}
+
+gboolean
+hal_device_is_recently_plugged_in (HalDevice *device)
+{
+ GTimeVal now;
+ glong delta_msec;
+
+ g_get_current_time (&now);
+
+ delta_msec = (now.tv_sec - device->priv->time_added.tv_sec) * 1000 +
+ (now.tv_usec - device->priv->time_added.tv_usec) / 1000;
+
+ return delta_msec < 2000;
+}
diff --git a/trunk/monitor/gphoto2/hal-device.h b/trunk/monitor/gphoto2/hal-device.h
new file mode 100644
index 00000000..8e91aa63
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-device.h
@@ -0,0 +1,93 @@
+/* hal-device.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef HAL_DEVICE_H
+#define HAL_DEVICE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <libhal.h>
+
+#define HAL_TYPE_DEVICE (hal_device_get_type ())
+#define HAL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_DEVICE, HalDevice))
+#define HAL_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_DEVICE, HalDeviceClass))
+#define HAL_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_DEVICE))
+#define HAL_IS_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_DEVICE))
+#define HAL_DEVICE_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_DEVICE, HalDeviceClass))
+
+
+typedef struct _HalDevice HalDevice;
+typedef struct _HalDeviceClass HalDeviceClass;
+
+struct _HalDevicePrivate;
+typedef struct _HalDevicePrivate HalDevicePrivate;
+
+struct _HalDevice
+{
+ GObject parent;
+
+ /* private */
+ HalDevicePrivate *priv;
+};
+
+struct _HalDeviceClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*hal_property_changed) (HalDevice *device, const char *key);
+ void (*hal_condition) (HalDevice *device, const char *name, const char *detail);
+};
+
+
+GType hal_device_get_type (void);
+
+HalDevice * hal_device_new_from_udi (LibHalContext *hal_ctx,
+ const char *udi);
+
+HalDevice * hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx,
+ char *udi,
+ LibHalPropertySet *properties);
+
+const char * hal_device_get_udi (HalDevice *device);
+LibHalPropertySet * hal_device_get_properties (HalDevice *device);
+const char * hal_device_get_property_string (HalDevice *device,
+ const char *key);
+int hal_device_get_property_int (HalDevice *device,
+ const char *key);
+guint64 hal_device_get_property_uint64 (HalDevice *device,
+ const char *key);
+double hal_device_get_property_double (HalDevice *device,
+ const char *key);
+gboolean hal_device_get_property_bool (HalDevice *device,
+ const char *key);
+char ** hal_device_get_property_strlist (HalDevice *device,
+ const char *key);
+
+gboolean hal_device_has_property (HalDevice *device,
+ const char *key);
+gboolean hal_device_has_capability (HalDevice *device,
+ const char *capability);
+gboolean hal_device_has_interface (HalDevice *device,
+ const char *interface);
+
+gboolean hal_device_is_recently_plugged_in (HalDevice *device);
+
+#endif /* HAL_DEVICE_H */
diff --git a/trunk/monitor/gphoto2/hal-marshal.c b/trunk/monitor/gphoto2/hal-marshal.c
new file mode 100644
index 00000000..75fec6e4
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-marshal.c
@@ -0,0 +1,163 @@
+#include "hal-marshal.h"
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:OBJECT,STRING (hal-marshal.list:1) */
+void
+hal_marshal_VOID__OBJECT_STRING (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ data2);
+}
+
+/* VOID:OBJECT,STRING,STRING (hal-marshal.list:2) */
+void
+hal_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer arg_3,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_string (param_values + 3),
+ data2);
+}
+
+/* VOID:STRING,STRING (hal-marshal.list:3) */
+void
+hal_marshal_VOID__STRING_STRING (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ data2);
+}
+
diff --git a/trunk/monitor/gphoto2/hal-marshal.h b/trunk/monitor/gphoto2/hal-marshal.h
new file mode 100644
index 00000000..0ac3074c
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-marshal.h
@@ -0,0 +1,36 @@
+
+#ifndef __hal_marshal_MARSHAL_H__
+#define __hal_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:OBJECT,STRING (hal-marshal.list:1) */
+extern void hal_marshal_VOID__OBJECT_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,STRING,STRING (hal-marshal.list:2) */
+extern void hal_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:STRING,STRING (hal-marshal.list:3) */
+extern void hal_marshal_VOID__STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* __hal_marshal_MARSHAL_H__ */
+
diff --git a/trunk/monitor/gphoto2/hal-marshal.list b/trunk/monitor/gphoto2/hal-marshal.list
new file mode 100644
index 00000000..52c82338
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-marshal.list
@@ -0,0 +1,3 @@
+VOID:OBJECT,STRING
+VOID:OBJECT,STRING,STRING
+VOID:STRING,STRING
diff --git a/trunk/monitor/gphoto2/hal-pool.c b/trunk/monitor/gphoto2/hal-pool.c
new file mode 100644
index 00000000..770effd9
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-pool.c
@@ -0,0 +1,458 @@
+/* hal-pool.c
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <gdbusutils.h>
+
+#include "hal-pool.h"
+#include "hal-marshal.h"
+
+enum {
+ DEVICE_ADDED,
+ DEVICE_REMOVED,
+ DEVICE_PROPERTY_CHANGED,
+ DEVICE_CONDITION,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _HalPoolPrivate
+{
+ char **cap_only;
+
+ DBusConnection *dbus_connection;
+ LibHalContext *hal_ctx;
+ GHashTable *devices;
+};
+
+G_DEFINE_TYPE (HalPool, hal_pool, G_TYPE_OBJECT)
+
+static void
+hal_pool_finalize (HalPool *pool)
+{
+ g_strfreev (pool->priv->cap_only);
+
+ dbus_bus_remove_match (pool->priv->dbus_connection,
+ "type='signal',"
+ "interface='org.freedesktop.Hal.Device',"
+ "sender='org.freedesktop.Hal'", NULL);
+ libhal_ctx_shutdown (pool->priv->hal_ctx, NULL);
+ dbus_connection_close (pool->priv->dbus_connection);
+ dbus_connection_unref (pool->priv->dbus_connection);
+
+ if (G_OBJECT_CLASS (hal_pool_parent_class)->finalize)
+ (* G_OBJECT_CLASS (hal_pool_parent_class)->finalize) (G_OBJECT (pool));
+}
+
+static void
+hal_pool_class_init (HalPoolClass *klass)
+{
+ GObjectClass *obj_class = (GObjectClass *) klass;
+
+ obj_class->finalize = (GObjectFinalizeFunc) hal_pool_finalize;
+
+ g_type_class_ref (HAL_TYPE_DEVICE);
+
+ signals[DEVICE_ADDED] =
+ g_signal_new ("device_added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ HAL_TYPE_DEVICE);
+
+ signals[DEVICE_REMOVED] =
+ g_signal_new ("device_removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ HAL_TYPE_DEVICE);
+
+ signals[DEVICE_PROPERTY_CHANGED] =
+ g_signal_new ("device_property_changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_property_changed),
+ NULL, NULL,
+ hal_marshal_VOID__OBJECT_STRING,
+ G_TYPE_NONE, 2,
+ HAL_TYPE_DEVICE,
+ G_TYPE_STRING);
+
+ signals[DEVICE_CONDITION] =
+ g_signal_new ("device_condition",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_condition),
+ NULL, NULL,
+ hal_marshal_VOID__OBJECT_STRING_STRING,
+ G_TYPE_NONE, 3,
+ HAL_TYPE_DEVICE,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+}
+
+static void
+hal_pool_init (HalPool *pool)
+{
+ pool->priv = g_new0 (HalPoolPrivate, 1);
+ pool->priv->hal_ctx = NULL;
+}
+
+static gboolean
+has_cap_only (HalPool *pool, HalDevice *device)
+{
+ const char *subsys;
+ unsigned int n;
+
+ for (n = 0; pool->priv->cap_only != NULL && pool->priv->cap_only[n] != NULL; n++)
+ {
+ if (hal_device_has_capability (device, pool->priv->cap_only[n]))
+ return TRUE;
+
+ subsys = hal_device_get_property_string (device, "info.subsystem");
+
+ if (subsys != NULL && strcmp (subsys, pool->priv->cap_only[n]) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+hal_pool_add_device_by_udi (HalPool *pool,
+ const char *udi,
+ gboolean emit_signal)
+{
+ HalDevice *device;
+
+ device = hal_device_new_from_udi (pool->priv->hal_ctx, udi);
+ if (device != NULL)
+ {
+ if (!has_cap_only (pool, device))
+ g_object_unref (device);
+ else
+ {
+ g_hash_table_insert (pool->priv->devices, g_strdup (udi), device);
+ if (emit_signal)
+ g_signal_emit (pool, signals[DEVICE_ADDED], 0, device);
+ }
+ }
+}
+
+#ifdef HAVE_HAL_FAST_INIT
+static void
+hal_pool_add_device_by_udi_and_properties (HalPool *pool,
+ char *udi,
+ LibHalPropertySet *properties,
+ gboolean emit_signal)
+{
+ HalDevice *device;
+
+ device = hal_device_new_from_udi_and_properties (pool->priv->hal_ctx, udi, properties);
+ if (device != NULL)
+ {
+ if (!has_cap_only (pool, device))
+ g_object_unref (device);
+ else
+ {
+ g_hash_table_insert (pool->priv->devices, g_strdup (udi), device);
+ if (emit_signal)
+ g_signal_emit (pool, signals[DEVICE_ADDED], 0, device);
+ }
+ }
+}
+#endif
+
+static void
+_hal_device_added (LibHalContext *hal_ctx, const char *udi)
+{
+ HalPool *pool;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx));
+ hal_pool_add_device_by_udi (pool, udi, TRUE);
+}
+
+static void
+_hal_device_removed (LibHalContext *hal_ctx, const char *udi)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx));
+ if ((device = hal_pool_get_device_by_udi (pool, udi)) != NULL)
+ {
+ g_object_ref (device);
+ g_hash_table_remove (pool->priv->devices, udi);
+ g_signal_emit (pool, signals[DEVICE_REMOVED], 0, device);
+ g_object_unref (device);
+ }
+}
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key);
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail);
+
+static void
+_hal_property_modified (LibHalContext *ctx,
+ const char *udi,
+ const char *key,
+ dbus_bool_t is_removed,
+ dbus_bool_t is_added)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (ctx));
+
+ device = hal_pool_get_device_by_udi (pool, udi);
+ if (device != NULL)
+ {
+ _hal_device_hal_property_changed (device, key);
+ g_signal_emit (pool, signals[DEVICE_PROPERTY_CHANGED], 0, device, key);
+ }
+}
+
+static void
+_hal_condition (LibHalContext *ctx,
+ const char *udi,
+ const char *condition_name,
+ const char *condition_detail)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (ctx));
+
+ device = hal_pool_get_device_by_udi (pool, udi);
+ if (device != NULL)
+ {
+ _hal_device_hal_condition (device, condition_name, condition_detail);
+ g_signal_emit (pool, signals[DEVICE_CONDITION], 0, device, condition_name, condition_detail);
+ }
+}
+
+LibHalContext *
+hal_pool_get_hal_ctx (HalPool *pool)
+{
+ return pool->priv->hal_ctx;
+}
+
+DBusConnection *
+hal_pool_get_dbus_connection (HalPool *pool)
+{
+ return pool->priv->dbus_connection;
+}
+
+HalPool *
+hal_pool_new (char **cap_only)
+{
+ int i;
+ char **devices;
+ int num_devices;
+ HalPool *pool;
+ LibHalContext *hal_ctx;
+ DBusError error;
+ DBusConnection *dbus_connection;
+#ifdef HAVE_HAL_FAST_INIT
+ LibHalPropertySet **properties;
+#endif
+
+ pool = NULL;
+
+ dbus_error_init (&error);
+ /* see discussion on gtk-devel-list (Subject: Re: gvfs hal volume monitoring backend) on
+ * why this is private
+ */
+ dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+ if (dbus_error_is_set (&error))
+ {
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
+
+ hal_ctx = libhal_ctx_new ();
+ if (hal_ctx == NULL)
+ {
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ goto out;
+ }
+
+ _g_dbus_connection_integrate_with_main (dbus_connection);
+ libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
+
+ if (!libhal_ctx_init (hal_ctx, &error))
+ {
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ pool = HAL_POOL (g_object_new (HAL_TYPE_POOL, NULL));
+ pool->priv->dbus_connection = dbus_connection;
+ pool->priv->hal_ctx = hal_ctx;
+ pool->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ pool->priv->cap_only = g_strdupv (cap_only);
+
+ /* Gah, unfortunately we have to watch all devices as HAL's PropertyModified signal
+ * doesn't include the capabilities...
+ */
+ dbus_bus_add_match (dbus_connection,
+ "type='signal',"
+ "interface='org.freedesktop.Hal.Device',"
+ "sender='org.freedesktop.Hal'", NULL);
+ libhal_ctx_set_device_added (hal_ctx, _hal_device_added);
+ libhal_ctx_set_device_removed (hal_ctx, _hal_device_removed);
+ libhal_ctx_set_device_property_modified (hal_ctx, _hal_property_modified);
+ libhal_ctx_set_device_condition (hal_ctx, _hal_condition);
+ libhal_ctx_set_user_data (hal_ctx, pool);
+
+#ifdef HAVE_HAL_FAST_INIT
+ /* First try new O(1) algorithm to get all devices and properties in a single call..
+ *
+ * This method is only available in post hal 0.5.10.
+ */
+ if (libhal_get_all_devices_with_properties (pool->priv->hal_ctx,
+ &num_devices,
+ &devices,
+ &properties,
+ NULL))
+ {
+ for (i = 0; i < num_devices; i++)
+ hal_pool_add_device_by_udi_and_properties (pool, devices[i], properties[i], FALSE);
+ libhal_free_string_array (devices);
+ free (properties); /* hal_pool_add_device_by_udi_and_properties steals the given properties */
+ goto out;
+ }
+#endif
+
+ /* fallback to using O(n) algorithm; will work on any hal 0.5.x release */
+ devices = libhal_get_all_devices (pool->priv->hal_ctx, &num_devices, NULL);
+ if (devices != NULL)
+ {
+ for (i = 0; i < num_devices; i++)
+ {
+ char *device_udi;
+ device_udi = devices[i];
+ hal_pool_add_device_by_udi (pool, device_udi, FALSE);
+ }
+ libhal_free_string_array (devices);
+ goto out;
+ }
+
+ /* FAIL! */
+
+ g_object_unref (pool);
+ return NULL;
+
+ out:
+ return pool;
+}
+
+HalDevice *
+hal_pool_get_device_by_udi (HalPool *pool, const char *udi)
+{
+ return g_hash_table_lookup (pool->priv->devices, udi);
+}
+
+HalDevice *
+hal_pool_get_device_by_capability_and_string (HalPool *pool,
+ const char *capability,
+ const char *key,
+ const char *value)
+{
+ GList *i;
+ GList *devices;
+ HalDevice *result;
+
+ result = NULL;
+ devices = NULL;
+
+ if (pool->priv->devices == NULL)
+ goto out;
+
+ devices = g_hash_table_get_values (pool->priv->devices);
+ for (i = devices; i != NULL; i = i->next)
+ {
+ HalDevice *d = i->data;
+ const char *s;
+
+ if (!hal_device_has_capability (d, capability))
+ continue;
+
+ s = hal_device_get_property_string (d, key);
+ if (s == NULL)
+ continue;
+
+ if (strcmp (s, value) == 0)
+ {
+ result = d;
+ goto out;
+ }
+ }
+
+out:
+ if (devices != NULL)
+ g_list_free (devices);
+ return result;
+}
+
+GList *
+hal_pool_find_by_capability (HalPool *pool, const char *capability)
+{
+ GList *i;
+ GList *j;
+ GList *devices;
+
+ devices = NULL;
+
+ if (pool->priv->devices == NULL)
+ goto out;
+
+ devices = g_hash_table_get_values (pool->priv->devices);
+ for (i = devices; i != NULL; i = j)
+ {
+ HalDevice *d = i->data;
+
+ j = i->next;
+
+ if (!hal_device_has_capability (d, capability))
+ devices = g_list_delete_link (devices, i);
+ }
+
+ out:
+ return devices;
+}
diff --git a/trunk/monitor/gphoto2/hal-pool.h b/trunk/monitor/gphoto2/hal-pool.h
new file mode 100644
index 00000000..04c8687d
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-pool.h
@@ -0,0 +1,74 @@
+/* hal-pool.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined(HAL_POOL_H)
+#define HAL_POOL_H
+
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include "hal-device.h"
+
+#define HAL_TYPE_POOL (hal_pool_get_type ())
+#define HAL_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_POOL, HalPool))
+#define HAL_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_POOL, HalPoolClass))
+#define HAL_IS_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_POOL))
+#define HAL_IS_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_POOL))
+#define HAL_POOL_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_POOL, HalPoolClass))
+
+
+typedef struct _HalPool HalPool;
+typedef struct _HalPoolClass HalPoolClass;
+
+struct _HalPoolPrivate;
+typedef struct _HalPoolPrivate HalPoolPrivate;
+
+struct _HalPool
+{
+ GObject parent;
+
+ /* private */
+ HalPoolPrivate *priv;
+};
+
+struct _HalPoolClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*device_added) (HalPool *pool, HalDevice *device);
+ void (*device_removed) (HalPool *pool, HalDevice *device);
+ void (*device_property_changed) (HalPool *pool, HalDevice *device, const char *key);
+ void (*device_condition) (HalPool *pool, HalDevice *device, const char *name, const char *detail);
+};
+
+GType hal_pool_get_type (void);
+HalPool * hal_pool_new (char **cap_only);
+LibHalContext * hal_pool_get_hal_ctx (HalPool *pool);
+DBusConnection * hal_pool_get_dbus_connection (HalPool *pool);
+HalDevice * hal_pool_get_device_by_udi (HalPool *pool,
+ const char *udi);
+HalDevice * hal_pool_get_device_by_capability_and_string (HalPool *pool,
+ const char *capability,
+ const char *key,
+ const char *value);
+GList * hal_pool_find_by_capability (HalPool *pool,
+ const char *capability);
+
+#endif /* HAL_POOL_H */
diff --git a/trunk/monitor/gphoto2/hal-utils.c b/trunk/monitor/gphoto2/hal-utils.c
new file mode 100644
index 00000000..ca90bc7c
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-utils.c
@@ -0,0 +1,142 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ * Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "string.h"
+
+#include "hal-utils.h"
+
+static const struct {
+ const char *disc_type;
+ const char *icon_name;
+ char *ui_name;
+ char *ui_name_blank;
+} disc_data[] = {
+ {"cd_rom", "media-optical-cd-rom", N_("CD-ROM Disc"), N_("Blank CD-ROM Disc")},
+ {"cd_r", "media-optical-cd-r", N_("CD-R Disc"), N_("Blank CD-R Disc")},
+ {"cd_rw", "media-optical-cd-rw", N_("CD-RW Disc"), N_("Blank CD-RW Disc")},
+ {"dvd_rom", "media-optical-dvd-rom", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")},
+ {"dvd_ram", "media-optical-dvd-ram", N_("DVD-RAM Disc"), N_("Blank DVD-RAM Disc")},
+ {"dvd_r", "media-optical-dvd-r", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")},
+ {"dvd_rw", "media-optical-dvd-rw", N_("DVD-RW Disc"), N_("Blank DVD-RW Disc")},
+ {"dvd_plus_r", "media-optical-dvd-r-plus", N_("DVD+R Disc"), N_("Blank DVD+R Disc")},
+ {"dvd_plus_rw", "media-optical-dvd-rw-plus", N_("DVD+RW Disc"), N_("Blank DVD+RW Disc")},
+ {"dvd_plus_r_dl", "media-optical-dvd-dl-r-plus", N_("DVD+R DL Disc"), N_("Blank DVD+R DL Disc")},
+ {"bd_rom", "media-optical-bd-rom", N_("Blu-Ray Disc"), N_("Blank Blu-Ray Disc")},
+ {"bd_r", "media-optical-bd-r", N_("Blu-Ray R Disc"), N_("Blank Blu-Ray R Disc")},
+ {"bd_re", "media-optical-bd-re", N_("Blu-Ray RW Disc"), N_("Blank Blu-Ray RW Disc")},
+ {"hddvd_rom", "media-optical-hddvd-rom", N_("HD DVD Disc"), N_("Blank HD DVD Disc")},
+ {"hddvd_r", "media-optical-hddvd-r", N_("HD DVD-R Disc"), N_("Blank HD DVD-R Disc")},
+ {"hddvd_rw", "media-optical-hddvd-rw", N_("HD DVD-RW Disc"), N_("Blank HD DVD-RW Disc")},
+ {"mo", "media-optical-mo", N_("MO Disc"), N_("Blank MO Disc")},
+ {NULL, "media-optical", N_("Disc"), N_("Blank Disc")}
+};
+
+const char *
+get_disc_icon (const char *disc_type)
+{
+ int n;
+
+ for (n = 0; disc_data[n].disc_type != NULL; n++)
+ {
+ if (strcmp (disc_data[n].disc_type, disc_type) == 0)
+ break;
+ }
+
+ return disc_data[n].icon_name;
+}
+
+const char *
+get_disc_name (const char *disc_type, gboolean is_blank)
+{
+ int n;
+
+ for (n = 0; disc_data[n].disc_type != NULL; n++)
+ {
+ if (strcmp (disc_data[n].disc_type, disc_type) == 0)
+ break;
+ }
+
+ if (is_blank)
+ return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name_blank);
+ else
+ return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name);
+}
+
+/*
+ * Creates a GThemedIcon from icon_name and creates default
+ * fallbacks from fallbacks. Is smart in the case that icon_name
+ * and fallbacks are identically.
+ * Note: See the GThemedIcon documentation for more information
+ * on default fallbacks
+ */
+GIcon *
+get_themed_icon_with_fallbacks (const char *icon_name,
+ const char *fallbacks)
+{
+ int i = 0, dashes = 0;
+ const char *p;
+ char *dashp;
+ char *last;
+ char **names;
+ GIcon *icon;
+
+ if (G_UNLIKELY (icon_name == NULL))
+ return NULL;
+
+ if (fallbacks == NULL)
+ return g_themed_icon_new (icon_name);
+
+ p = fallbacks;
+ while (*p)
+ {
+ if (*p == '-')
+ dashes++;
+ p++;
+ }
+
+ if (strcmp (icon_name, fallbacks))
+ {
+ names = g_new (char *, dashes + 3);
+ names[i++] = g_strdup (icon_name);
+ }
+ else
+ names = g_new (char *, dashes + 2);
+
+ names[i++] = last = g_strdup (fallbacks);
+
+ while ((dashp = strrchr (last, '-')) != NULL)
+ names[i++] = last = g_strndup (last, dashp - last);
+
+ names[i++] = NULL;
+ icon = g_themed_icon_new_from_names (names, -1);
+ g_strfreev (names);
+
+ return icon;
+}
+
diff --git a/trunk/monitor/gphoto2/hal-utils.h b/trunk/monitor/gphoto2/hal-utils.h
new file mode 100644
index 00000000..7244a29c
--- /dev/null
+++ b/trunk/monitor/gphoto2/hal-utils.h
@@ -0,0 +1,40 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ * Chrsitian Kellner <gicmo@gnome.org>
+ */
+
+#ifndef __HAL_UTILS_H__
+#define __HAL_UTILS_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+const char * get_disc_icon (const char *disc_type);
+const char * get_disc_name (const char *disc_type, gboolean is_blank);
+
+GIcon * get_themed_icon_with_fallbacks (const char *icon_name,
+ const char *fallbacks);
+
+G_END_DECLS
+
+#endif /* __HAL_UTILS_H__ */
diff --git a/trunk/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in b/trunk/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in
new file mode 100644
index 00000000..b06e3df6
--- /dev/null
+++ b/trunk/monitor/gphoto2/org.gtk.Private.GPhoto2VolumeMonitor.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.Private.GPhoto2VolumeMonitor
+Exec=@libexecdir@/gvfs-gphoto2-volume-monitor
diff --git a/trunk/monitor/hal/Makefile.am b/trunk/monitor/hal/Makefile.am
new file mode 100644
index 00000000..9c3d1777
--- /dev/null
+++ b/trunk/monitor/hal/Makefile.am
@@ -0,0 +1,62 @@
+
+NULL =
+
+libexec_PROGRAMS = gvfs-hal-volume-monitor
+
+BUILT_SOURCES = \
+ hal-marshal.h hal-marshal.c
+
+hal-marshal.h: hal-marshal.list
+ glib-genmarshal $< --prefix=hal_marshal --header > $@
+
+hal-marshal.c: hal-marshal.list
+ echo "#include \"hal-marshal.h\"" > $@ && glib-genmarshal $< --prefix=hal_marshal --body >> $@
+
+
+gvfs_hal_volume_monitor_SOURCES = \
+ hal-utils.c hal-utils.h \
+ hal-volume-monitor-daemon.c \
+ hal-marshal.c hal-marshal.h \
+ hal-device.c hal-device.h \
+ hal-pool.c hal-pool.h \
+ ghaldrive.c ghaldrive.h \
+ ghalvolume.c ghalvolume.h \
+ ghalmount.c ghalmount.h \
+ ghalvolumemonitor.c ghalvolumemonitor.h \
+ $(NULL)
+
+gvfs_hal_volume_monitor_CFLAGS = \
+ -DG_LOG_DOMAIN=\"GVFS-Hal\" \
+ -I$(top_srcdir)/common \
+ -I$(top_srcdir)/monitor/proxy \
+ $(GLIB_CFLAGS) \
+ $(HAL_CFLAGS) \
+ -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+gvfs_hal_volume_monitor_LDFLAGS = \
+ $(NULL)
+
+gvfs_hal_volume_monitor_LDADD = \
+ $(GLIB_LIBS) \
+ $(HAL_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \
+ $(NULL)
+
+remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors
+remote_volume_monitors_DATA = hal.monitor
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gtk.Private.HalVolumeMonitor.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+clean-local:
+ rm -f *~ *.loT $(BUILT_SOURCES) $(service_DATA)
+
+EXTRA_DIST = hal-marshal.list $(service_in_files) hal.monitor
diff --git a/trunk/monitor/hal/ghaldrive.c b/trunk/monitor/hal/ghaldrive.c
new file mode 100644
index 00000000..b6f3814e
--- /dev/null
+++ b/trunk/monitor/hal/ghaldrive.c
@@ -0,0 +1,936 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include "ghalvolumemonitor.h"
+#include "ghaldrive.h"
+#include "ghalvolume.h"
+
+struct _GHalDrive {
+ GObject parent;
+
+ GVolumeMonitor *volume_monitor; /* owned by volume monitor */
+ GList *volumes; /* entries in list are owned by volume_monitor */
+
+ char *name;
+ char *icon;
+ char *device_path;
+
+ gboolean can_eject;
+ gboolean can_poll_for_media;
+ gboolean is_media_check_automatic;
+ gboolean has_media;
+ gboolean uses_removable_media;
+
+ HalDevice *device;
+ HalPool *pool;
+};
+
+static void g_hal_drive_drive_iface_init (GDriveIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GHalDrive, g_hal_drive, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_DRIVE,
+ g_hal_drive_drive_iface_init))
+
+static void
+g_hal_drive_finalize (GObject *object)
+{
+ GList *l;
+ GHalDrive *drive;
+
+ drive = G_HAL_DRIVE (object);
+
+ for (l = drive->volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+ g_hal_volume_unset_drive (volume, drive);
+ }
+
+ g_free (drive->device_path);
+ if (drive->device != NULL)
+ g_object_unref (drive->device);
+ if (drive->pool != NULL)
+ g_object_unref (drive->pool);
+
+ g_free (drive->name);
+ g_free (drive->icon);
+
+ if (drive->volume_monitor != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (drive->volume_monitor), (gpointer) &(drive->volume_monitor));
+
+ if (G_OBJECT_CLASS (g_hal_drive_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_hal_drive_parent_class)->finalize) (object);
+}
+
+static void
+g_hal_drive_class_init (GHalDriveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_hal_drive_finalize;
+}
+
+static void
+g_hal_drive_init (GHalDrive *hal_drive)
+{
+}
+
+static char *
+_drive_get_description (HalDevice *d)
+{
+ char *s = NULL;
+ const char *drive_type;
+ const char *drive_bus;
+ const char *name_from_hal;
+
+ drive_type = hal_device_get_property_string (d, "storage.drive_type");
+ drive_bus = hal_device_get_property_string (d, "storage.bus");
+ name_from_hal = hal_device_get_property_string (d, "info.desktop.name");
+
+
+ if (strlen (name_from_hal) > 0)
+ {
+ s = g_strdup (name_from_hal);
+ }
+ else if (strcmp (drive_type, "cdrom") == 0)
+ {
+ const char *first;
+ const char *second;
+
+ first = _("CD-ROM");
+ if (hal_device_get_property_bool (d, "storage.cdrom.cdr"))
+ first = _("CD-R");
+ if (hal_device_get_property_bool (d, "storage.cdrom.cdrw"))
+ first = _("CD-RW");
+
+ second = NULL;
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvd"))
+ second = _("DVD-ROM");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdplusr"))
+ second = _("DVD+R");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdplusrw"))
+ second = _("DVD+RW");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdr"))
+ second = _("DVD-R");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdrw"))
+ second = _("DVD-RW");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdram"))
+ second = _("DVD-RAM");
+ if ((hal_device_get_property_bool (d, "storage.cdrom.dvdr")) &&
+ (hal_device_get_property_bool (d, "storage.cdrom.dvdplusr")))
+ second = _("DVD\xc2\xb1R");
+ if (hal_device_get_property_bool (d, "storage.cdrom.dvdrw") &&
+ hal_device_get_property_bool (d, "storage.cdrom.dvdplusrw"))
+ second = _("DVD\xc2\xb1RW");
+ if (hal_device_get_property_bool (d, "storage.cdrom.hddvd"))
+ second = _("HDDVD");
+ if (hal_device_get_property_bool (d, "storage.cdrom.hddvdr"))
+ second = _("HDDVD-r");
+ if (hal_device_get_property_bool (d, "storage.cdrom.hddvdrw"))
+ second = _("HDDVD-RW");
+ if (hal_device_get_property_bool (d, "storage.cdrom.bd"))
+ second = _("Blu-ray");
+ if (hal_device_get_property_bool (d, "storage.cdrom.bdr"))
+ second = _("Blu-ray-R");
+ if (hal_device_get_property_bool (d, "storage.cdrom.bdre"))
+ second = _("Blu-ray-RE");
+
+ if (second != NULL)
+ {
+ /* translators: This wis something like "CD-ROM/DVD Drive" or
+ "CD-RW/Blue-ray Drive" depending on the properties of the drive */
+ s = g_strdup_printf (_("%s/%s Drive"), first, second);
+ }
+ else
+ {
+ /* translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+ depending on the properties of the drive */
+ s = g_strdup_printf (_("%s Drive"), first);
+ }
+ }
+ else if (strcmp (drive_type, "floppy") == 0)
+ s = g_strdup (_("Floppy Drive"));
+ else if (strcmp (drive_type, "disk") == 0)
+ {
+ if (drive_bus != NULL)
+ {
+ if (strcmp (drive_bus, "linux_raid") == 0)
+ s = g_strdup (_("Software RAID Drive"));
+ if (strcmp (drive_bus, "usb") == 0)
+ s = g_strdup (_("USB Drive"));
+ if (strcmp (drive_bus, "ide") == 0)
+ s = g_strdup (_("ATA Drive"));
+ if (strcmp (drive_bus, "scsi") == 0)
+ s = g_strdup (_("SCSI Drive"));
+ if (strcmp (drive_bus, "ieee1394") == 0)
+ s = g_strdup (_("FireWire Drive"));
+ }
+ }
+ else if (strcmp (drive_type, "tape") == 0)
+ s = g_strdup (_("Tape Drive"));
+ else if (strcmp (drive_type, "compact_flash") == 0)
+ s = g_strdup (_("CompactFlash Drive"));
+ else if (strcmp (drive_type, "memory_stick") == 0)
+ s = g_strdup (_("MemoryStick Drive"));
+ else if (strcmp (drive_type, "smart_media") == 0)
+ s = g_strdup (_("SmartMedia Drive"));
+ else if (strcmp (drive_type, "sd_mmc") == 0)
+ s = g_strdup (_("SD/MMC Drive"));
+ else if (strcmp (drive_type, "zip") == 0)
+ s = g_strdup (_("Zip Drive"));
+ else if (strcmp (drive_type, "jaz") == 0)
+ s = g_strdup (_("Jaz Drive"));
+ else if (strcmp (drive_type, "flashkey") == 0)
+ s = g_strdup (_("Thumb Drive"));
+
+ if (s == NULL)
+ s = g_strdup (_("Mass Storage Drive"));
+
+ return s;
+}
+
+char *
+_drive_get_icon (HalDevice *d)
+{
+ char *s = NULL;
+ const char *drive_type;
+ const char *drive_bus;
+ const char *icon_from_hal;
+ gboolean is_audio_player;
+
+ drive_type = hal_device_get_property_string (d, "storage.drive_type");
+ drive_bus = hal_device_get_property_string (d, "storage.bus");
+ is_audio_player = hal_device_has_capability (d, "portable_audio_player");
+ icon_from_hal = hal_device_get_property_string (d, "storage.icon.drive");
+
+ if (strlen (icon_from_hal) > 0)
+ s = g_strdup (icon_from_hal);
+ else if (is_audio_player)
+ s = g_strdup ("multimedia-player");
+ else if (strcmp (drive_type, "disk") == 0)
+ {
+ if (strcmp (drive_bus, "ide") == 0)
+ s = g_strdup ("drive-removable-media-ata");
+ else if (strcmp (drive_bus, "scsi") == 0)
+ s = g_strdup ("drive-removable-media-scsi");
+ else if (strcmp (drive_bus, "ieee1394") == 0)
+ s = g_strdup ("drive-removable-media-ieee1394");
+ else if (strcmp (drive_bus, "usb") == 0)
+ s = g_strdup ("drive-removable-media-usb");
+ else
+ s = g_strdup ("drive-removable-media");
+ }
+ else if (strcmp (drive_type, "cdrom") == 0)
+ {
+ /* TODO: maybe there's a better heuristic than this */
+ if (hal_device_get_property_int (d, "storage.cdrom.write_speed") > 0)
+ s = g_strdup ("drive-optical-recorder");
+ else
+ s = g_strdup ("drive-optical");
+ }
+ else if (strcmp (drive_type, "floppy") == 0)
+ s = g_strdup ("drive-removable-media-floppy");
+ else if (strcmp (drive_type, "tape") == 0)
+ s = g_strdup ("drive-removable-media-tape");
+ else if (strcmp (drive_type, "compact_flash") == 0)
+ s = g_strdup ("drive-removable-media-flash-cf");
+ else if (strcmp (drive_type, "memory_stick") == 0)
+ s = g_strdup ("drive-removable-media-flash-ms");
+ else if (strcmp (drive_type, "smart_media") == 0)
+ s = g_strdup ("drive-removable-media-flash-sm");
+ else if (strcmp (drive_type, "sd_mmc") == 0)
+ s = g_strdup ("drive-removable-media-flash-sd");
+
+ if (s == NULL)
+ s = g_strdup ("drive-removable-media");
+
+ return s;
+}
+
+static void
+_do_update_from_hal (GHalDrive *d)
+{
+ d->name = _drive_get_description (d->device);
+ d->icon = _drive_get_icon (d->device);
+
+ d->uses_removable_media = hal_device_get_property_bool (d->device, "storage.removable");
+ if (d->uses_removable_media)
+ {
+ d->has_media = hal_device_get_property_bool (d->device, "storage.removable.media_available");
+ d->is_media_check_automatic = hal_device_get_property_bool (d->device, "storage.media_check_enabled");
+ d->can_poll_for_media = hal_device_has_interface (d->device, "org.freedesktop.Hal.Device.Storage.Removable");
+ d->can_eject = hal_device_get_property_bool (d->device, "storage.requires_eject");
+ }
+ else
+ {
+ d->has_media = TRUE;
+ d->is_media_check_automatic = FALSE;
+ d->can_poll_for_media = FALSE;
+ d->can_eject = FALSE;
+ }
+}
+
+static void
+emit_drive_changed (GHalDrive *drive)
+{
+ g_signal_emit_by_name (drive, "changed");
+ if (drive->volume_monitor != NULL)
+ g_signal_emit_by_name (drive->volume_monitor, "drive_changed", drive);
+}
+
+static void
+_update_from_hal (GHalDrive *d, gboolean emit_changed)
+{
+ char *old_name;
+ char *old_icon;
+ gboolean old_uses_removable_media;
+ gboolean old_has_media;
+ gboolean old_is_media_check_automatic;
+ gboolean old_can_poll_for_media;
+ gboolean old_can_eject;
+
+ old_name = g_strdup (d->name);
+ old_icon = g_strdup (d->icon);
+ old_uses_removable_media = d->uses_removable_media;
+ old_has_media = d->has_media;
+ old_is_media_check_automatic = d->is_media_check_automatic;
+ old_can_poll_for_media = d->can_poll_for_media;
+ old_can_eject = d->can_eject;
+
+ g_free (d->name);
+ g_free (d->icon);
+ _do_update_from_hal (d);
+
+ if (emit_changed &&
+ (old_uses_removable_media != d->uses_removable_media ||
+ old_has_media != d->has_media ||
+ old_is_media_check_automatic != d->is_media_check_automatic ||
+ old_can_poll_for_media != d->can_poll_for_media ||
+ old_can_eject != d->can_eject ||
+ old_name == NULL ||
+ old_icon == NULL ||
+ strcmp (old_name, d->name) != 0 ||
+ strcmp (old_icon, d->icon) != 0))
+ emit_drive_changed (d);
+
+ g_free (old_name);
+ g_free (old_icon);
+}
+
+static void
+hal_condition (HalDevice *device, const char *name, const char *detail, gpointer user_data)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (user_data);
+
+ if (strcmp (name, "EjectPressed") == 0)
+ {
+ g_signal_emit_by_name (hal_drive, "eject-button");
+ if (hal_drive->volume_monitor != NULL)
+ g_signal_emit_by_name (hal_drive->volume_monitor, "drive-eject-button", hal_drive);
+ }
+
+}
+
+static void
+hal_changed (HalDevice *device, const char *key, gpointer user_data)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (user_data);
+
+ /*g_warning ("volhal modifying %s (property %s changed)", hal_drive->device_path, key);*/
+ _update_from_hal (hal_drive, TRUE);
+}
+
+GHalDrive *
+g_hal_drive_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool)
+{
+ GHalDrive *drive;
+
+ drive = g_object_new (G_TYPE_HAL_DRIVE, NULL);
+ drive->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(drive->volume_monitor));
+ drive->device_path = g_strdup (hal_device_get_property_string (device, "block.device"));
+ drive->device = g_object_ref (device);
+ drive->pool = g_object_ref (pool);
+
+ drive->name = g_strdup_printf ("Drive for %s", drive->device_path);
+ drive->icon = g_strdup_printf ("drive-removable-media");
+
+ g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, drive, 0);
+ g_signal_connect_object (device, "hal_condition", (GCallback) hal_condition, drive, 0);
+
+ _update_from_hal (drive, FALSE);
+
+ return drive;
+}
+
+void
+g_hal_drive_disconnected (GHalDrive *drive)
+{
+ GList *l, *volumes;
+
+ volumes = drive->volumes;
+ drive->volumes = NULL;
+
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+ g_hal_volume_unset_drive (volume, drive);
+ }
+
+ g_list_free (volumes);
+}
+
+void
+g_hal_drive_set_volume (GHalDrive *drive,
+ GHalVolume *volume)
+{
+
+ if (g_list_find (drive->volumes, volume) == NULL)
+ {
+ drive->volumes = g_list_prepend (drive->volumes, volume);
+ emit_drive_changed (drive);
+ }
+}
+
+void
+g_hal_drive_unset_volume (GHalDrive *drive,
+ GHalVolume *volume)
+{
+ GList *l;
+
+ l = g_list_find (drive->volumes, volume);
+ if (l != NULL)
+ {
+ drive->volumes = g_list_delete_link (drive->volumes, l);
+
+ emit_drive_changed (drive);
+ }
+}
+
+gboolean
+g_hal_drive_has_udi (GHalDrive *drive, const char *udi)
+{
+ gboolean res;
+
+ res = strcmp (udi, hal_device_get_udi (drive->device)) == 0;
+
+ return res;
+}
+
+static GIcon *
+g_hal_drive_get_icon (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ GIcon *icon;
+
+ icon = g_themed_icon_new_with_default_fallbacks (hal_drive->icon);
+
+ return icon;
+}
+
+static char *
+g_hal_drive_get_name (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ char *name;
+
+ name = g_strdup (hal_drive->name);
+
+ return name;
+}
+
+static GList *
+g_hal_drive_get_volumes (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ GList *l;
+
+ l = g_list_copy (hal_drive->volumes);
+ g_list_foreach (l, (GFunc) g_object_ref, NULL);
+
+ return l;
+}
+
+static gboolean
+g_hal_drive_has_volumes (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+
+ return hal_drive->volumes != NULL;
+}
+
+static gboolean
+g_hal_drive_is_media_removable (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+
+ return hal_drive->uses_removable_media;
+}
+
+static gboolean
+g_hal_drive_has_media (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+
+ return hal_drive->has_media;
+}
+
+static gboolean
+g_hal_drive_is_media_check_automatic (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+
+ return hal_drive->is_media_check_automatic;
+}
+
+static gboolean
+g_hal_drive_can_eject (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ gboolean res;
+
+ return hal_drive->can_eject;
+}
+
+static gboolean
+g_hal_drive_can_poll_for_media (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+
+ return hal_drive->can_poll_for_media;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} SpawnOp;
+
+static void
+spawn_cb (GPid pid, gint status, gpointer user_data)
+{
+ SpawnOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ GError *error;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED_HANDLED,
+ "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI");
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ }
+ else
+ {
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ }
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_hal_drive_eject_do (GDrive *drive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ SpawnOp *data;
+ GPid child_pid;
+ GError *error;
+ char *argv[] = {"gnome-mount", "-e", "-b", "-d", NULL, NULL};
+
+ argv[4] = g_strdup (hal_drive->device_path);
+
+ data = g_new0 (SpawnOp, 1);
+ data->object = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ error = NULL;
+ if (!g_spawn_async (NULL, /* working dir */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data for child_setup */
+ &child_pid,
+ &error))
+ {
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_object_unref (drive);
+ g_error_free (error);
+ g_free (data);
+ }
+ else
+ g_child_watch_add (child_pid, spawn_cb, data);
+
+ g_free (argv[4]);
+}
+
+
+typedef struct {
+ GDrive *drive;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+ GMountUnmountFlags flags;
+
+ GList *pending_mounts;
+} UnmountMountsOp;
+
+static void
+free_unmount_mounts_op (UnmountMountsOp *data)
+{
+ GList *l;
+
+ for (l = data->pending_mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = l->data;
+ g_object_unref (mount);
+ }
+ g_list_free (data->pending_mounts);
+}
+
+static void _eject_unmount_mounts (UnmountMountsOp *data);
+
+static void
+_eject_unmount_mounts_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ UnmountMountsOp *data = user_data;
+ GMount *mount = G_MOUNT (source_object);
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ if (!g_mount_unmount_finish (mount, res, &error))
+ {
+ /* make the error dialog more targeted to the drive.. unless the user has already seen a dialog */
+ if (error->code != G_IO_ERROR_FAILED_HANDLED)
+ {
+ g_error_free (error);
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("Failed to eject media; one or more volumes on the media are busy."));
+ }
+
+ /* unmount failed; need to fail the whole eject operation */
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ free_unmount_mounts_op (data);
+ }
+ else
+ {
+
+ /*g_warning ("successfully unmounted %p", mount);*/
+
+ /* move on to the next mount.. */
+ _eject_unmount_mounts (data);
+ }
+
+ g_object_unref (mount);
+}
+
+static void
+_eject_unmount_mounts (UnmountMountsOp *data)
+{
+ GMount *mount;
+
+ if (data->pending_mounts == NULL)
+ {
+
+ /*g_warning ("all pending mounts done; ejecting drive");*/
+
+ g_hal_drive_eject_do (data->drive,
+ data->cancellable,
+ data->callback,
+ data->user_data);
+
+ g_object_unref (data->drive);
+ g_free (data);
+ }
+ else
+ {
+ mount = data->pending_mounts->data;
+ data->pending_mounts = g_list_remove (data->pending_mounts, mount);
+
+ /*g_warning ("unmounting %p", mount);*/
+
+ g_mount_unmount (mount,
+ data->flags,
+ data->cancellable,
+ _eject_unmount_mounts_cb,
+ data);
+ }
+}
+
+static void
+g_hal_drive_eject (GDrive *drive,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ UnmountMountsOp *data;
+ GList *l;
+
+ /* first we need to go through all the volumes and unmount their assoicated mounts (if any) */
+
+ data = g_new0 (UnmountMountsOp, 1);
+ data->drive = g_object_ref (drive);
+ data->cancellable = cancellable;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->flags = flags;
+
+ for (l = hal_drive->volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+ GMount *mount; /* the mount may be foreign; cannot assume GHalMount */
+
+ mount = g_volume_get_mount (G_VOLUME (volume));
+ if (mount != NULL && g_mount_can_unmount (mount))
+ data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount));
+ }
+
+ _eject_unmount_mounts (data);
+}
+
+static gboolean
+g_hal_drive_eject_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} PollOp;
+
+static void
+poll_for_media_cb (DBusPendingCall *pending_call, void *user_data)
+{
+ PollOp *data = (PollOp *) user_data;
+ GSimpleAsyncResult *simple;
+ DBusMessage *reply;
+
+ reply = dbus_pending_call_steal_reply (pending_call);
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ GError *error;
+ DBusError dbus_error;
+
+ dbus_error_init (&dbus_error);
+ dbus_set_error_from_message (&dbus_error, reply);
+ error = g_error_new (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Cannot invoke CheckForMedia on HAL: %s: %s", dbus_error.name, dbus_error.message);
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ /* TODO: parse reply and extract result?
+ * (the result is whether the media availability state changed)
+ */
+
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ out:
+ g_object_unref (data->object);
+ dbus_message_unref (reply);
+ dbus_pending_call_unref (pending_call);
+}
+
+
+static void
+g_hal_drive_poll_for_media (GDrive *drive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ DBusConnection *con;
+ DBusMessage *msg;
+ DBusPendingCall *pending_call;
+ PollOp *data;
+
+ data = g_new0 (PollOp, 1);
+ data->object = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ /*g_warning ("Rescanning udi %s", hal_device_get_udi (hal_drive->device));*/
+
+ con = hal_pool_get_dbus_connection (hal_drive->pool);
+ msg = dbus_message_new_method_call ("org.freedesktop.Hal",
+ hal_device_get_udi (hal_drive->device),
+ "org.freedesktop.Hal.Device.Storage.Removable",
+ "CheckForMedia");
+
+ if (!dbus_connection_send_with_reply (con, msg, &pending_call, -1))
+ {
+ GError *error;
+ GSimpleAsyncResult *simple;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Cannot invoke CheckForMedia on HAL");
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ g_object_unref (data->object);
+ g_free (data);
+ }
+ else
+ dbus_pending_call_set_notify (pending_call,
+ poll_for_media_cb,
+ data,
+ (DBusFreeFunction) g_free);
+
+ dbus_message_unref (msg);
+}
+
+static gboolean
+g_hal_drive_poll_for_media_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ /*g_warning ("poll finish");*/
+ return TRUE;
+}
+
+static char *
+g_hal_drive_get_identifier (GDrive *drive,
+ const char *kind)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ char *res;
+
+ res = NULL;
+
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0)
+ res = g_strdup (hal_device_get_udi (hal_drive->device));
+
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+ res = g_strdup (hal_drive->device_path);
+
+ return res;
+}
+
+static char **
+g_hal_drive_enumerate_identifiers (GDrive *drive)
+{
+ GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+ GPtrArray *res;
+
+ res = g_ptr_array_new ();
+
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI));
+
+ if (hal_drive->device_path && *hal_drive->device_path != 0)
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE));
+
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **)g_ptr_array_free (res, FALSE);
+}
+
+static void
+g_hal_drive_drive_iface_init (GDriveIface *iface)
+{
+ iface->get_name = g_hal_drive_get_name;
+ iface->get_icon = g_hal_drive_get_icon;
+ iface->has_volumes = g_hal_drive_has_volumes;
+ iface->get_volumes = g_hal_drive_get_volumes;
+ iface->is_media_removable = g_hal_drive_is_media_removable;
+ iface->has_media = g_hal_drive_has_media;
+ iface->is_media_check_automatic = g_hal_drive_is_media_check_automatic;
+ iface->can_eject = g_hal_drive_can_eject;
+ iface->can_poll_for_media = g_hal_drive_can_poll_for_media;
+ iface->eject = g_hal_drive_eject;
+ iface->eject_finish = g_hal_drive_eject_finish;
+ iface->poll_for_media = g_hal_drive_poll_for_media;
+ iface->poll_for_media_finish = g_hal_drive_poll_for_media_finish;
+ iface->get_identifier = g_hal_drive_get_identifier;
+ iface->enumerate_identifiers = g_hal_drive_enumerate_identifiers;
+}
diff --git a/trunk/monitor/hal/ghaldrive.h b/trunk/monitor/hal/ghaldrive.h
new file mode 100644
index 00000000..7832db59
--- /dev/null
+++ b/trunk/monitor/hal/ghaldrive.h
@@ -0,0 +1,62 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_HAL_DRIVE_H__
+#define __G_HAL_DRIVE_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "hal-pool.h"
+#include "ghalvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_HAL_DRIVE (g_hal_drive_get_type ())
+#define G_HAL_DRIVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_HAL_DRIVE, GHalDrive))
+#define G_HAL_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_HAL_DRIVE, GHalDriveClass))
+#define G_IS_HAL_DRIVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_HAL_DRIVE))
+#define G_IS_HAL_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_HAL_DRIVE))
+
+typedef struct _GHalDriveClass GHalDriveClass;
+
+struct _GHalDriveClass {
+ GObjectClass parent_class;
+};
+
+GType g_hal_drive_get_type (void) G_GNUC_CONST;
+
+GHalDrive *g_hal_drive_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool);
+gboolean g_hal_drive_has_udi (GHalDrive *drive,
+ const char *udi);
+void g_hal_drive_set_volume (GHalDrive *drive,
+ GHalVolume *volume);
+void g_hal_drive_unset_volume (GHalDrive *drive,
+ GHalVolume *volume);
+void g_hal_drive_disconnected (GHalDrive *drive);
+char * _drive_get_icon (HalDevice *d);
+
+G_END_DECLS
+
+#endif /* __G_HAL_DRIVE_H__ */
diff --git a/trunk/monitor/hal/ghalmount.c b/trunk/monitor/hal/ghalmount.c
new file mode 100644
index 00000000..2c84f4b4
--- /dev/null
+++ b/trunk/monitor/hal/ghalmount.c
@@ -0,0 +1,1132 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gvfsmountinfo.h>
+
+#include "ghalvolumemonitor.h"
+#include "ghalmount.h"
+#include "ghalvolume.h"
+
+#include "hal-utils.h"
+
+struct _GHalMount {
+ GObject parent;
+
+ GVolumeMonitor *volume_monitor; /* owned by volume monitor */
+ GHalVolume *volume; /* owned by volume monitor */
+
+ char *name;
+ GIcon *icon;
+ char *device_path;
+ char *mount_path;
+
+ char *uuid;
+
+ char *override_name;
+ GIcon *override_icon;
+ GFile *override_root;
+ gboolean cannot_unmount;
+
+ HalDevice *device;
+ HalDevice *drive_device;
+
+ GIcon *autorun_icon;
+ gboolean searched_for_autorun;
+
+ gchar *xdg_volume_info_name;
+ GIcon *xdg_volume_info_icon;
+ gboolean searched_for_xdg_volume_info;
+};
+
+static GFile *get_root (GHalMount *hal_mount);
+
+static void update_from_hal (GHalMount *m, gboolean emit_changed);
+
+static void g_hal_mount_mount_iface_init (GMountIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GHalMount, g_hal_mount, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
+ g_hal_mount_mount_iface_init))
+
+static void
+g_hal_mount_finalize (GObject *object)
+{
+ GHalMount *mount;
+
+ mount = G_HAL_MOUNT (object);
+
+ if (mount->volume != NULL)
+ g_hal_volume_unset_mount (mount->volume, mount);
+
+ g_free (mount->device_path);
+ g_free (mount->mount_path);
+ g_free (mount->uuid);
+
+ if (mount->device != NULL)
+ g_object_unref (mount->device);
+ if (mount->drive_device != NULL)
+ g_object_unref (mount->drive_device);
+
+ g_free (mount->name);
+ if (mount->icon != NULL)
+ g_object_unref (mount->icon);
+
+ g_free (mount->override_name);
+ if (mount->override_icon != NULL)
+ g_object_unref (mount->override_icon);
+
+ if (mount->override_root != NULL)
+ g_object_unref (mount->override_root);
+
+ if (mount->autorun_icon != NULL)
+ g_object_unref (mount->autorun_icon);
+
+ g_free (mount->xdg_volume_info_name);
+ if (mount->xdg_volume_info_icon != NULL)
+ g_object_unref (mount->xdg_volume_info_icon);
+
+ if (mount->volume_monitor != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor));
+
+ if (G_OBJECT_CLASS (g_hal_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_hal_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_hal_mount_class_init (GHalMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_hal_mount_finalize;
+}
+
+static void
+g_hal_mount_init (GHalMount *hal_mount)
+{
+}
+
+static void
+emit_mount_changed (GHalMount *mount)
+{
+ g_signal_emit_by_name (mount, "changed");
+ if (mount->volume_monitor != NULL)
+ g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
+}
+
+#define KILOBYTE_FACTOR 1000.0
+#define MEGABYTE_FACTOR (1000.0 * 1000.0)
+#define GIGABYTE_FACTOR (1000.0 * 1000.0 * 1000.0)
+
+static char *
+format_size_for_display (guint64 size)
+{
+ char *str;
+ gdouble displayed_size;
+
+ if (size < MEGABYTE_FACTOR)
+ {
+ displayed_size = (double) size / KILOBYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f kB"), displayed_size);
+ }
+ else if (size < GIGABYTE_FACTOR)
+ {
+ displayed_size = (double) size / MEGABYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f MB"), displayed_size);
+ }
+ else
+ {
+ displayed_size = (double) size / GIGABYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f GB"), displayed_size);
+ }
+
+ return str;
+}
+
+static void
+got_autorun_info_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GHalMount *mount = G_HAL_MOUNT (user_data);
+
+ mount->autorun_icon = g_vfs_mount_info_query_autorun_info_finish (G_FILE (source_object),
+ res,
+ NULL);
+
+ update_from_hal (mount, TRUE);
+
+ g_object_unref (mount);
+}
+
+static void
+got_xdg_volume_info_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GHalMount *mount = G_HAL_MOUNT (user_data);
+
+ mount->xdg_volume_info_icon = g_vfs_mount_info_query_xdg_volume_info_finish (G_FILE (source_object),
+ res,
+ &(mount->xdg_volume_info_name),
+ NULL);
+ update_from_hal (mount, TRUE);
+
+ g_object_unref (mount);
+}
+
+static void
+do_update_from_hal (GHalMount *m)
+{
+ HalDevice *volume;
+ HalDevice *drive;
+ char *name;
+ const char *icon_name;
+ const char *icon_name_fallback;
+ const char *drive_type;
+ const char *drive_bus;
+ gboolean drive_uses_removable_media;
+ const char *volume_fs_label;
+ guint64 volume_size;
+ gboolean volume_is_disc;
+ gboolean volume_disc_has_audio;
+ gboolean volume_disc_has_data;
+ const char *volume_disc_type;
+ gboolean volume_disc_is_blank;
+ gboolean is_audio_player;
+ const char *icon_from_hal;
+ const char *volume_icon_from_hal;
+ const char *name_from_hal;
+ const char *volume_name_from_hal;
+ gboolean is_crypto;
+ gboolean is_crypto_cleartext;
+
+ volume = m->device;
+ drive = m->drive_device;
+
+ drive_type = hal_device_get_property_string (drive, "storage.drive_type");
+ drive_bus = hal_device_get_property_string (drive, "storage.bus");
+ drive_uses_removable_media = hal_device_get_property_bool (drive, "storage.removable");
+ volume_fs_label = hal_device_get_property_string (volume, "volume.label");
+ volume_size = hal_device_get_property_uint64 (volume, "volume.size");
+ volume_is_disc = hal_device_get_property_bool (volume, "volume.is_disc");
+ volume_disc_has_audio = hal_device_get_property_bool (volume, "volume.disc.has_audio");
+ volume_disc_has_data = hal_device_get_property_bool (volume, "volume.disc.has_data");
+ volume_disc_is_blank = hal_device_get_property_bool (volume, "volume.disc.is_blank");
+ volume_disc_type = hal_device_get_property_string (volume, "volume.disc.type");
+ is_audio_player = hal_device_has_capability (drive, "portable_audio_player");
+ icon_from_hal = hal_device_get_property_string (drive, "storage.icon.drive");
+ volume_icon_from_hal = hal_device_get_property_string (volume, "storage.icon.volume");
+ name_from_hal = hal_device_get_property_string (drive, "info.desktop.name");
+ volume_name_from_hal = hal_device_get_property_string (volume, "info.desktop.name");
+
+ is_crypto = FALSE;
+ is_crypto_cleartext = FALSE;
+ if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0)
+ is_crypto = TRUE;
+
+ if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0)
+ is_crypto_cleartext = TRUE;
+
+ /*g_warning ("drive_type='%s'", drive_type); */
+ /*g_warning ("drive_bus='%s'", drive_bus); */
+ /*g_warning ("drive_uses_removable_media=%d", drive_uses_removable_media); */
+
+ icon_name_fallback = NULL;
+
+ if (strlen (volume_icon_from_hal) > 0)
+ icon_name = volume_icon_from_hal;
+ else if (strlen (icon_from_hal) > 0)
+ icon_name = icon_from_hal;
+ else if (is_audio_player)
+ icon_name = "multimedia-player";
+ else if (strcmp (drive_type, "disk") == 0)
+ {
+ if (strcmp (drive_bus, "ide") == 0)
+ icon_name = "drive-harddisk-ata";
+ else if (strcmp (drive_bus, "scsi") == 0)
+ icon_name = "drive-harddisk-scsi";
+ else if (strcmp (drive_bus, "ieee1394") == 0)
+ icon_name = "drive-harddisk-ieee1394";
+ else if (strcmp (drive_bus, "usb") == 0)
+ icon_name = "drive-harddisk-usb";
+ else
+ icon_name = "drive-harddisk";
+ }
+ else if (strcmp (drive_type, "cdrom") == 0)
+ icon_name = get_disc_icon (volume_disc_type);
+ else if (strcmp (drive_type, "floppy") == 0)
+ icon_name = "media-floppy";
+ else if (strcmp (drive_type, "tape") == 0)
+ icon_name = "media-tape";
+ else if (strcmp (drive_type, "compact_flash") == 0)
+ icon_name = "media-flash-cf";
+ else if (strcmp (drive_type, "memory_stick") == 0)
+ icon_name = "media-flash-ms";
+ else if (strcmp (drive_type, "smart_media") == 0)
+ icon_name = "media-flash-sm";
+ else if (strcmp (drive_type, "sd_mmc") == 0)
+ icon_name = "media-flash-sd";
+ else
+ icon_name = "drive-harddisk";
+
+ /* Create default fallbacks for the icon_name by default
+ * with get_themed_icon_with_fallbacks () */
+ icon_name_fallback = icon_name;
+
+ /* Note: we are not chaning the default fallbacks
+ * so we get all the fallbacks if the media-encrytped
+ * icon is not there */
+ if (is_crypto || is_crypto_cleartext)
+ icon_name = "media-encrypted";
+
+ if (strlen (volume_name_from_hal) > 0)
+ name = g_strdup (volume_name_from_hal);
+ else if (strlen (name_from_hal) > 0)
+ name = g_strdup (name_from_hal);
+ else if (volume_fs_label != NULL && strlen (volume_fs_label) > 0)
+ name = g_strdup (volume_fs_label);
+ else if (volume_is_disc)
+ {
+ if (volume_disc_has_audio)
+ {
+ if (volume_disc_has_data)
+ name = g_strdup (_("Mixed Audio/Data Disc"));
+ else
+ name = g_strdup (_("Audio Disc"));
+ }
+ else
+ name = g_strdup (get_disc_name (volume_disc_type, volume_disc_is_blank));
+ }
+ else
+ {
+ char *size;
+
+ size = format_size_for_display (volume_size);
+ /* Translators: %s is the size of the mount (e.g. 512 MB) */
+ name = g_strdup_printf (_("%s Media"), size);
+ g_free (size);
+ }
+
+ /* order of preference : xdg, override, probed */
+ if (m->xdg_volume_info_name != NULL)
+ {
+ m->name = g_strdup (m->xdg_volume_info_name);
+ g_free (name);
+ }
+ else if (m->override_name != NULL)
+ {
+ m->name = g_strdup (m->override_name);
+ g_free (name);
+ }
+ else
+ m->name = name;
+
+ /* order of preference: xdg, autorun, override, probed */
+ if (m->xdg_volume_info_icon != NULL)
+ m->icon = g_object_ref (m->xdg_volume_info_icon);
+ else if (m->autorun_icon != NULL)
+ m->icon = g_object_ref (m->autorun_icon);
+ else if (m->override_icon != NULL)
+ m->icon = g_object_ref (m->override_icon);
+ else
+ m->icon = get_themed_icon_with_fallbacks (icon_name,
+ icon_name_fallback);
+
+ /* search for .xdg-volume-info */
+ if (!m->searched_for_xdg_volume_info)
+ {
+ GFile *root;
+ root = get_root (m);
+ m->searched_for_xdg_volume_info = TRUE;
+ g_vfs_mount_info_query_xdg_volume_info (root,
+ NULL,
+ got_xdg_volume_info_cb,
+ g_object_ref (m));
+ g_object_unref (root);
+ }
+
+ /* search for autorun.inf */
+ if (!m->searched_for_autorun)
+ {
+ GFile *root;
+ root = get_root (m);
+ m->searched_for_autorun = TRUE;
+ g_vfs_mount_info_query_autorun_info (root,
+ NULL,
+ got_autorun_info_cb,
+ g_object_ref (m));
+ g_object_unref (root);
+ }
+}
+
+
+static void
+update_from_hal (GHalMount *m, gboolean emit_changed)
+{
+ char *old_name;
+ GIcon *old_icon;
+
+ old_name = g_strdup (m->name);
+ old_icon = m->icon != NULL ? g_object_ref (m->icon) : NULL;
+
+ g_free (m->name);
+ if (m->icon != NULL)
+ g_object_unref (m->icon);
+ do_update_from_hal (m);
+
+ if (emit_changed)
+ {
+ if (old_name == NULL ||
+ old_icon == NULL ||
+ strcmp (old_name, m->name) != 0 ||
+ (! g_icon_equal (old_icon, m->icon)))
+ emit_mount_changed (m);
+ }
+ g_free (old_name);
+ if (old_icon != NULL)
+ g_object_unref (old_icon);
+}
+
+static void
+hal_changed (HalDevice *device, const char *key, gpointer user_data)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (user_data);
+
+ /*g_warning ("mounthal modifying %s (property %s changed)", hal_mount->device_path, key); */
+ update_from_hal (hal_mount, TRUE);
+}
+
+static void
+compute_uuid (GHalMount *mount)
+{
+ const char *fs_uuid;
+ const char *fs_label;
+
+ /* use the FS uuid before falling back to the FS label */
+
+ fs_uuid = hal_device_get_property_string (mount->device, "volume.uuid");
+ fs_label = hal_device_get_property_string (mount->device, "volume.label");
+
+ if (strlen (fs_uuid) == 0)
+ {
+ if (strlen (fs_label) == 0)
+ mount->uuid = NULL;
+ else
+ mount->uuid = g_strdup (fs_label);
+ }
+ else
+ mount->uuid = g_strdup (fs_uuid);
+}
+
+
+GHalMount *
+g_hal_mount_new_for_hal_device (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ GFile *override_root,
+ const char *override_name,
+ GIcon *override_icon,
+ gboolean cannot_unmount,
+ HalPool *pool,
+ GHalVolume *volume)
+{
+ HalDevice *drive_device;
+ const char *storage_udi;
+ GHalMount *mount;
+
+ storage_udi = hal_device_get_property_string (device, "block.storage_device");
+ if (storage_udi == NULL)
+ goto fail;
+
+ /* g_warning ("storage_udi = %s", storage_udi); */
+
+ drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+ if (drive_device == NULL)
+ goto fail;
+
+ /* g_warning ("drive_device = %p", drive_device); */
+
+ mount = g_object_new (G_TYPE_HAL_MOUNT, NULL);
+ mount->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (mount->volume_monitor), (gpointer) &(mount->volume_monitor));
+ mount->device_path = g_strdup (hal_device_get_property_string (device, "block.device"));
+ mount->mount_path = g_strdup ("/");
+ mount->device = g_object_ref (device);
+ mount->drive_device = g_object_ref (drive_device);
+ mount->override_root = override_root != NULL ? g_object_ref (override_root) : NULL;
+ mount->override_icon = override_icon != NULL ? g_object_ref (override_icon) : NULL;
+ mount->override_name = g_strdup (override_name);
+ mount->cannot_unmount = cannot_unmount;
+
+ g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, mount, 0);
+ g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, mount, 0);
+
+ compute_uuid (mount);
+ update_from_hal (mount, FALSE);
+
+ /* need to do this last */
+ mount->volume = volume;
+ if (volume != NULL)
+ g_hal_volume_set_mount (volume, mount);
+
+ return mount;
+
+ fail:
+ return NULL;
+}
+
+void
+g_hal_mount_override_name (GHalMount *mount, const char *name)
+{
+ g_free (mount->override_name);
+
+ if (name != NULL)
+ mount->override_name = g_strdup (name);
+ else
+ mount->override_name = NULL;
+
+ update_from_hal (mount, TRUE);
+}
+
+void
+g_hal_mount_override_icon (GHalMount *mount, GIcon *icon)
+{
+ if (mount->override_icon != NULL)
+ g_object_unref (mount->override_icon);
+
+ if (icon != NULL)
+ mount->override_icon = g_object_ref (icon);
+ else
+ mount->override_icon = NULL;
+
+ update_from_hal (mount, TRUE);
+}
+
+GHalMount *
+g_hal_mount_new (GVolumeMonitor *volume_monitor,
+ GUnixMountEntry *mount_entry,
+ HalPool *pool,
+ GHalVolume *volume)
+{
+ HalDevice *device;
+ HalDevice *drive_device;
+ const char *storage_udi;
+ GHalMount *mount;
+
+ /* If no volume for mount - Ignore internal things */
+ if (volume == NULL && !g_unix_mount_guess_should_display (mount_entry))
+ return NULL;
+
+ mount = g_object_new (G_TYPE_HAL_MOUNT, NULL);
+ mount->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(mount->volume_monitor));
+ mount->device_path = g_strdup (g_unix_mount_get_device_path (mount_entry));
+ mount->mount_path = g_strdup (g_unix_mount_get_mount_path (mount_entry));
+ mount->device = NULL;
+ mount->drive_device = NULL;
+ mount->uuid = NULL;
+
+ if (pool != NULL)
+ {
+ device = hal_pool_get_device_by_capability_and_string (pool,
+ "volume",
+ "block.device",
+ mount->device_path);
+ /* g_warning ("device = %p for %s", device, mount->device_path); */
+ if (device != NULL)
+ {
+ /* g_warning ("udi = %s", hal_device_get_udi (device)); */
+
+ storage_udi = hal_device_get_property_string (device, "block.storage_device");
+ if (storage_udi == NULL)
+ goto not_hal;
+
+ /* g_warning ("storage_udi = %s", storage_udi); */
+
+ drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+ if (drive_device == NULL)
+ goto not_hal;
+
+ /* g_warning ("drive_device = %p", drive_device); */
+
+ mount->device = g_object_ref (device);
+ mount->drive_device = g_object_ref (drive_device);
+
+ g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, mount, 0);
+ g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, mount, 0);
+
+ compute_uuid (mount);
+ update_from_hal (mount, FALSE);
+
+ goto was_hal;
+ }
+ }
+
+ not_hal:
+
+ if (volume != NULL)
+ {
+ g_object_unref (mount);
+ return NULL;
+ }
+
+ mount->name = g_unix_mount_guess_name (mount_entry);
+ mount->icon = g_unix_mount_guess_icon (mount_entry);
+
+ was_hal:
+
+ /* need to do this last */
+ mount->volume = volume;
+ if (volume != NULL)
+ g_hal_volume_set_mount (volume, mount);
+
+ return mount;
+}
+
+void
+g_hal_mount_unmounted (GHalMount *mount)
+{
+ if (mount->volume != NULL)
+ {
+ g_hal_volume_unset_mount (mount->volume, mount);
+ mount->volume = NULL;
+ emit_mount_changed (mount);
+ }
+}
+
+void
+g_hal_mount_unset_volume (GHalMount *mount,
+ GHalVolume *volume)
+{
+ if (mount->volume == volume)
+ {
+ mount->volume = NULL;
+ emit_mount_changed (mount);
+ }
+}
+
+static GFile *
+get_root (GHalMount *hal_mount)
+{
+ if (hal_mount->override_root != NULL)
+ return g_object_ref (hal_mount->override_root);
+ else
+ return g_file_new_for_path (hal_mount->mount_path);
+}
+
+static GFile *
+g_hal_mount_get_root (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+
+ return get_root (hal_mount);
+}
+
+static GIcon *
+g_hal_mount_get_icon (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+
+ return g_object_ref (hal_mount->icon);
+}
+
+static char *
+g_hal_mount_get_uuid (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+
+ return g_strdup (hal_mount->uuid);
+}
+
+static char *
+g_hal_mount_get_name (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+
+ return g_strdup (hal_mount->name);
+}
+
+gboolean
+g_hal_mount_has_uuid (GHalMount *mount,
+ const char *uuid)
+{
+ gboolean res;
+
+ res = FALSE;
+ if (mount->uuid != NULL)
+ res = strcmp (mount->uuid, uuid) == 0;
+
+ return res;
+}
+
+gboolean
+g_hal_mount_has_mount_path (GHalMount *mount,
+ const char *mount_path)
+{
+ return strcmp (mount->mount_path, mount_path) == 0;
+}
+
+gboolean
+g_hal_mount_has_udi (GHalMount *mount,
+ const char *udi)
+{
+ gboolean res;
+
+ res = FALSE;
+ if (mount->device != NULL)
+ res = strcmp (hal_device_get_udi (mount->device), udi) == 0;
+
+ return res;
+}
+
+static GDrive *
+g_hal_mount_get_drive (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ GDrive *drive;
+
+ drive = NULL;
+ if (hal_mount->volume != NULL)
+ drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+
+ return drive;
+}
+
+static GVolume *
+g_hal_mount_get_volume (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ GVolume *volume;
+
+ volume = NULL;
+ if (hal_mount->volume)
+ volume = G_VOLUME (g_object_ref (hal_mount->volume));
+
+ return volume;
+}
+
+static gboolean
+g_hal_mount_can_unmount (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ gboolean res;
+
+ res = TRUE;
+ if (hal_mount->cannot_unmount)
+ res = FALSE;
+
+ return res;
+}
+
+static gboolean
+g_hal_mount_can_eject (GMount *mount)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ GDrive *drive;
+ gboolean can_eject;
+
+ can_eject = FALSE;
+ if (hal_mount->volume != NULL)
+ {
+ drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+ if (drive != NULL)
+ can_eject = g_drive_can_eject (drive);
+ }
+
+ return can_eject;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+ int error_fd;
+ GIOChannel *error_channel;
+ guint error_channel_source_id;
+ GString *error_string;
+ gboolean using_legacy;
+} UnmountOp;
+
+static void
+unmount_cb (GPid pid, gint status, gpointer user_data)
+{
+ UnmountOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ if (data->using_legacy)
+ {
+ GError *error;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ data->error_string->str);
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ }
+ else
+ {
+ GError *error;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED_HANDLED,
+ "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI");
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ g_source_remove (data->error_channel_source_id);
+ g_io_channel_unref (data->error_channel);
+ g_string_free (data->error_string, TRUE);
+ close (data->error_fd);
+ g_spawn_close_pid (pid);
+
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static gboolean
+unmount_read_error (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ char *str;
+ gsize str_len;
+ UnmountOp *data = user_data;
+
+ g_io_channel_read_to_end (channel, &str, &str_len, NULL);
+ g_string_append (data->error_string, str);
+ g_free (str);
+ return TRUE;
+}
+
+static void
+unmount_do (GMount *mount,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ char **argv,
+ gboolean using_legacy)
+{
+ UnmountOp *data;
+ GPid child_pid;
+ GError *error;
+
+ data = g_new0 (UnmountOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+ data->using_legacy = using_legacy;
+
+ error = NULL;
+ if (!g_spawn_async_with_pipes (NULL, /* working dir */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data for child_setup */
+ &child_pid,
+ NULL, /* standard_input */
+ NULL, /* standard_output */
+ &(data->error_fd),
+ &error))
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ g_free (data);
+ return;
+ }
+ data->error_string = g_string_new ("");
+ data->error_channel = g_io_channel_unix_new (data->error_fd);
+ data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, unmount_read_error, data);
+ g_child_watch_add (child_pid, unmount_cb, data);
+}
+
+
+static void
+g_hal_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ char *argv[] = {"gnome-mount", "-u", "-b", "-d", NULL, NULL};
+ gboolean using_legacy = FALSE;
+ char *d, *m;
+
+ d = g_strdup (hal_mount->device_path);
+ m = g_strdup (hal_mount->mount_path);
+
+ if (hal_mount->device != NULL)
+ argv[4] = d;
+ else
+ {
+ using_legacy = TRUE;
+ argv[0] = "umount";
+ argv[1] = m;
+ argv[2] = NULL;
+ }
+
+ unmount_do (mount, cancellable, callback, user_data, argv, using_legacy);
+ g_free (d);
+ g_free (m);
+}
+
+static gboolean
+g_hal_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_hal_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ GDrive *drive;
+
+ drive = NULL;
+ if (hal_mount->volume != NULL)
+ drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_hal_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ GDrive *drive;
+ gboolean res;
+
+ res = TRUE;
+
+ drive = NULL;
+ if (hal_mount->volume != NULL)
+ drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+
+ if (drive != NULL)
+ {
+ res = g_drive_eject_finish (drive, result, error);
+ g_object_unref (drive);
+ }
+ return res;
+}
+
+/* TODO: handle force_rescan */
+static char **
+g_hal_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GHalMount *hal_mount = G_HAL_MOUNT (mount);
+ const char *disc_type;
+ char **x_content_types;
+ GFile *root;
+ GPtrArray *p;
+ char **result;
+ int n;
+ char **caps;
+ char *uri;
+
+ p = g_ptr_array_new ();
+
+ root = get_root (hal_mount);
+ uri = g_file_get_uri (root);
+ if (g_str_has_prefix (uri, "burn://"))
+ {
+ /* doesn't make sense to probe burn:/// - look at the disc type instead */
+ if (hal_mount->device != NULL)
+ {
+ disc_type = hal_device_get_property_string (hal_mount->device, "volume.disc.type");
+ if (disc_type != NULL)
+ {
+ if (g_str_has_prefix (disc_type, "dvd"))
+ g_ptr_array_add (p, g_strdup ("x-content/blank-dvd"));
+ else if (g_str_has_prefix (disc_type, "hddvd"))
+ g_ptr_array_add (p, g_strdup ("x-content/blank-hddvd"));
+ else if (g_str_has_prefix (disc_type, "bd"))
+ g_ptr_array_add (p, g_strdup ("x-content/blank-bd"));
+ else
+ g_ptr_array_add (p, g_strdup ("x-content/blank-cd")); /* assume CD */
+ }
+ }
+ }
+ else
+ {
+ /* sniff content type */
+ x_content_types = g_content_type_guess_for_tree (root);
+ if (x_content_types != NULL)
+ {
+ for (n = 0; x_content_types[n] != NULL; n++)
+ g_ptr_array_add (p, g_strdup (x_content_types[n]));
+ g_strfreev (x_content_types);
+ }
+ }
+ g_object_unref (root);
+ g_free (uri);
+
+ /* also add content types from hal capabilities */
+ if (hal_mount->drive_device != NULL)
+ {
+ caps = dupv_and_uniqify (hal_device_get_property_strlist (hal_mount->drive_device, "info.capabilities"));
+ if (caps != NULL)
+ {
+ for (n = 0; caps[n] != NULL; n++)
+ {
+ if (strcmp (caps[n], "portable_audio_player") == 0)
+ g_ptr_array_add (p, g_strdup ("x-content/audio-player"));
+ }
+ g_strfreev (caps);
+ }
+ }
+
+ if (p->len == 0)
+ {
+ result = NULL;
+ g_ptr_array_free (p, TRUE);
+ }
+ else
+ {
+ g_ptr_array_add (p, NULL);
+ result = (char **) g_ptr_array_free (p, FALSE);
+ }
+
+ return result;
+}
+
+/* since we're an out-of-process volume monitor we'll just do this sync */
+static void
+g_hal_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ /* TODO: handle force_rescan */
+ simple = g_simple_async_result_new (G_OBJECT (mount),
+ callback,
+ user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static char **
+g_hal_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ /* TODO: handle force_rescan */
+ return g_hal_mount_guess_content_type_sync (mount, FALSE, NULL, error);
+}
+
+static void
+g_hal_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_hal_mount_get_root;
+ iface->get_name = g_hal_mount_get_name;
+ iface->get_icon = g_hal_mount_get_icon;
+ iface->get_uuid = g_hal_mount_get_uuid;
+ iface->get_drive = g_hal_mount_get_drive;
+ iface->get_volume = g_hal_mount_get_volume;
+ iface->can_unmount = g_hal_mount_can_unmount;
+ iface->can_eject = g_hal_mount_can_eject;
+ iface->unmount = g_hal_mount_unmount;
+ iface->unmount_finish = g_hal_mount_unmount_finish;
+ iface->eject = g_hal_mount_eject;
+ iface->eject_finish = g_hal_mount_eject_finish;
+ iface->guess_content_type = g_hal_mount_guess_content_type;
+ iface->guess_content_type_finish = g_hal_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_hal_mount_guess_content_type_sync;
+}
diff --git a/trunk/monitor/hal/ghalmount.h b/trunk/monitor/hal/ghalmount.h
new file mode 100644
index 00000000..31981aed
--- /dev/null
+++ b/trunk/monitor/hal/ghalmount.h
@@ -0,0 +1,76 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_HAL_MOUNT_H__
+#define __G_HAL_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "hal-pool.h"
+#include "ghalvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_HAL_MOUNT (g_hal_mount_get_type ())
+#define G_HAL_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_HAL_MOUNT, GHalMount))
+#define G_HAL_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_HAL_MOUNT, GHalMountClass))
+#define G_IS_HAL_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_HAL_MOUNT))
+#define G_IS_HAL_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_HAL_MOUNT))
+
+typedef struct _GHalMountClass GHalMountClass;
+
+struct _GHalMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_hal_mount_get_type (void) G_GNUC_CONST;
+
+GHalMount * g_hal_mount_new_for_hal_device (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ GFile *override_root,
+ const char *override_name,
+ GIcon *override_icon,
+ gboolean cannot_unmount,
+ HalPool *pool,
+ GHalVolume *volume);
+GHalMount * g_hal_mount_new (GVolumeMonitor *volume_monitor,
+ GUnixMountEntry *mount_entry,
+ HalPool *pool,
+ GHalVolume *volume);
+gboolean g_hal_mount_has_mount_path (GHalMount *mount,
+ const char *mount_path);
+gboolean g_hal_mount_has_udi (GHalMount *mount,
+ const char *udi);
+gboolean g_hal_mount_has_uuid (GHalMount *mount,
+ const char *uuid);
+void g_hal_mount_unset_volume (GHalMount *mount,
+ GHalVolume *volume);
+void g_hal_mount_unmounted (GHalMount *mount);
+void g_hal_mount_override_name (GHalMount *mount,
+ const char *name);
+void g_hal_mount_override_icon (GHalMount *mount,
+ GIcon *icon);
+
+G_END_DECLS
+
+#endif /* __G_HAL_MOUNT_H__ */
diff --git a/trunk/monitor/hal/ghalvolume.c b/trunk/monitor/hal/ghalvolume.c
new file mode 100644
index 00000000..47dda661
--- /dev/null
+++ b/trunk/monitor/hal/ghalvolume.c
@@ -0,0 +1,986 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "ghaldrive.h"
+#include "ghalvolume.h"
+#include "ghalmount.h"
+
+#include "hal-utils.h"
+
+struct _GHalVolume {
+ GObject parent;
+
+ GVolumeMonitor *volume_monitor; /* owned by volume monitor */
+ GHalMount *mount; /* owned by volume monitor */
+ GHalDrive *drive; /* owned by volume monitor */
+
+ char *device_path;
+ char *mount_path;
+ char *uuid;
+ HalDevice *device;
+ HalDevice *drive_device;
+
+ /* set on creation if we won't create a GHalMount object ourselves
+ * and instead except to adopt one, with the given mount root,
+ * via adopt_orphan_mount()
+ */
+ GFile *foreign_mount_root;
+ GMount *foreign_mount;
+ gboolean is_mountable;
+ gboolean ignore_automount;
+
+ char *name;
+ char *icon;
+ char *icon_fallback;
+};
+
+static void g_hal_volume_volume_iface_init (GVolumeIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GHalVolume, g_hal_volume, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
+ g_hal_volume_volume_iface_init))
+
+static void
+g_hal_volume_finalize (GObject *object)
+{
+ GHalVolume *volume;
+
+ volume = G_HAL_VOLUME (object);
+
+ if (volume->mount != NULL)
+ g_hal_mount_unset_volume (volume->mount, volume);
+
+ if (volume->drive != NULL)
+ g_hal_drive_unset_volume (volume->drive, volume);
+
+ g_free (volume->mount_path);
+ g_free (volume->device_path);
+ g_free (volume->uuid);
+ if (volume->device != NULL)
+ g_object_unref (volume->device);
+ if (volume->drive_device != NULL)
+ g_object_unref (volume->drive_device);
+
+ if (volume->foreign_mount_root != NULL)
+ g_object_unref (volume->foreign_mount_root);
+
+ if (volume->foreign_mount != NULL)
+ g_object_unref (volume->foreign_mount);
+
+ if (volume->volume_monitor != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (volume->volume_monitor), (gpointer) &(volume->volume_monitor));
+
+ g_free (volume->name);
+ g_free (volume->icon);
+ g_free (volume->icon_fallback);
+
+ if (G_OBJECT_CLASS (g_hal_volume_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_hal_volume_parent_class)->finalize) (object);
+}
+
+static void
+g_hal_volume_class_init (GHalVolumeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_hal_volume_finalize;
+}
+
+static void
+g_hal_volume_init (GHalVolume *hal_volume)
+{
+}
+
+static void
+emit_volume_changed (GHalVolume *volume)
+{
+ g_signal_emit_by_name (volume, "changed");
+ if (volume->volume_monitor != NULL)
+ g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+}
+
+#define KILOBYTE_FACTOR 1000.0
+#define MEGABYTE_FACTOR (1000.0 * 1000.0)
+#define GIGABYTE_FACTOR (1000.0 * 1000.0 * 1000.0)
+
+/**
+ * format_size_for_display:
+ * @size: a number of octects
+ *
+ * Format a human readable string that can conveys how much storage a
+ * user-visible drive or piece of media can hold.
+ *
+ * As a matter of policy, we want this string to resemble what's on
+ * the packaging of the drive/media. Since all manufacturers use
+ * powers of 10, g_format_size_for_display() is not suitable here.
+ *
+ * TODO: we probably want to round to nearest power of two if @size is
+ * "close" (e.g. within 5%) - this is to avoid e.g. 63.4G when the
+ * packaging says "64G drive". We could also use per-drive or
+ * per-media quirks to make a better guess.
+ *
+ * Returns: A human readable string, caller must free it using
+ * g_free().
+ **/
+static char *
+format_size_for_display (guint64 size)
+{
+ char *str;
+ gdouble displayed_size;
+
+ if (size < MEGABYTE_FACTOR)
+ {
+ displayed_size = (double) size / KILOBYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f kB"), displayed_size);
+ }
+ else if (size < GIGABYTE_FACTOR)
+ {
+ displayed_size = (double) size / MEGABYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f MB"), displayed_size);
+ }
+ else
+ {
+ displayed_size = (double) size / GIGABYTE_FACTOR;
+ str = g_strdup_printf (_("%.1f GB"), displayed_size);
+ }
+
+ return str;
+}
+
+static void
+do_update_from_hal (GHalVolume *mv)
+{
+ const char *drive_type;
+ const char *drive_bus;
+ gboolean drive_uses_removable_media;
+ const char *volume_fs_label;
+ guint64 volume_size;
+ gboolean volume_is_disc;
+ gboolean volume_disc_has_audio;
+ gboolean volume_disc_has_data;
+ const char *volume_disc_type;
+ gboolean volume_disc_is_blank;
+ const char *volume_fsusage;
+ const char *volume_fstype;
+ HalDevice *volume;
+ HalDevice *drive;
+ char *name;
+ char *size;
+ gboolean is_crypto;
+ gboolean is_crypto_cleartext;
+
+ volume = mv->device;
+ drive = mv->drive_device;
+
+ drive_type = hal_device_get_property_string (drive, "storage.drive_type");
+ drive_bus = hal_device_get_property_string (drive, "storage.bus");
+ drive_uses_removable_media = hal_device_get_property_bool (drive, "storage.removable");
+ volume_fs_label = hal_device_get_property_string (volume, "volume.label");
+ volume_size = hal_device_get_property_uint64 (volume, "volume.size");
+ volume_is_disc = hal_device_get_property_bool (volume, "volume.is_disc");
+ volume_disc_has_audio = hal_device_get_property_bool (volume, "volume.disc.has_audio");
+ volume_disc_has_data = hal_device_get_property_bool (volume, "volume.disc.has_data");
+ volume_disc_is_blank = hal_device_get_property_bool (volume, "volume.disc.is_blank");
+ volume_disc_type = hal_device_get_property_string (volume, "volume.disc.type");
+ volume_fsusage = hal_device_get_property_string (volume, "volume.fsusage");
+ volume_fstype = hal_device_get_property_string (volume, "volume.fstype");
+
+ is_crypto = FALSE;
+ is_crypto_cleartext = FALSE;
+ if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0)
+ is_crypto = TRUE;
+ if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0)
+ is_crypto_cleartext = TRUE;
+
+ if (volume_is_disc && volume_disc_has_audio && mv->foreign_mount_root != NULL)
+ name = g_strdup (_("Audio Disc"));
+ else
+ {
+ if (strcmp (volume_fsusage, "crypto") == 0 && strcmp (volume_fstype, "crypto_LUKS") == 0)
+ {
+ size = format_size_for_display (volume_size);
+ /* Translators: %s is the size of the volume (e.g. 512 MB) */
+ name = g_strdup_printf (_("%s Encrypted Data"), size);
+ g_free (size);
+ }
+ else
+ {
+ if (volume_fs_label != NULL && strlen (volume_fs_label) > 0)
+ name = g_strdup (volume_fs_label);
+ else if (volume_is_disc)
+ {
+ if (volume_disc_has_audio)
+ {
+ if (volume_disc_has_data)
+ name = g_strdup (_("Mixed Audio/Data Disc"));
+ else
+ name = g_strdup (_("Audio Disc"));
+ }
+ else
+ name = g_strdup (get_disc_name (volume_disc_type, volume_disc_is_blank));
+ }
+ else
+ {
+ size = format_size_for_display (volume_size);
+ /* Translators: %s is the size of the volume (e.g. 512 MB) */
+ name = g_strdup_printf (_("%s Media"), size);
+ g_free (size);
+ }
+ }
+ }
+
+ mv->name = name;
+ mv->icon = _drive_get_icon (drive); /* use the drive icon since we're unmounted */
+
+ if (is_crypto || is_crypto_cleartext)
+ {
+ mv->icon_fallback = mv->icon;
+ mv->icon = g_strdup ("drive-encrypted");
+ }
+
+ if (hal_device_get_property_bool (volume, "volume.is_mounted"))
+ mv->mount_path = g_strdup (hal_device_get_property_string (volume, "volume.mount_point"));
+ else
+ mv->mount_path = NULL;
+
+ g_object_set_data_full (G_OBJECT (mv),
+ "hal-storage-device-capabilities",
+ dupv_and_uniqify (hal_device_get_property_strlist (mv->drive_device, "info.capabilities")),
+ (GDestroyNotify) g_strfreev);
+
+ if (volume_disc_type != NULL && strlen (volume_disc_type) == 0)
+ volume_disc_type = NULL;
+ g_object_set_data_full (G_OBJECT (mv),
+ "hal-volume.disc.type",
+ g_strdup (volume_disc_type),
+ (GDestroyNotify) g_free);
+}
+
+static void
+update_from_hal (GHalVolume *mv, gboolean emit_changed)
+{
+ char *old_name;
+ char *old_icon;
+ char *old_mount_path;
+
+ old_name = g_strdup (mv->name);
+ old_icon = g_strdup (mv->icon);
+ old_mount_path = g_strdup (mv->mount_path);
+
+ g_free (mv->name);
+ g_free (mv->icon);
+ g_free (mv->mount_path);
+ do_update_from_hal (mv);
+
+ if (emit_changed)
+ {
+ gboolean mount_path_changed;
+
+ if ((old_mount_path == NULL && mv->mount_path != NULL) ||
+ (old_mount_path != NULL && mv->mount_path == NULL) ||
+ (old_mount_path != NULL && mv->mount_path != NULL && strcmp (old_mount_path, mv->mount_path) != 0))
+ mount_path_changed = TRUE;
+ else
+ mount_path_changed = FALSE;
+
+ if (mount_path_changed ||
+ (old_name == NULL ||
+ old_icon == NULL ||
+ strcmp (old_name, mv->name) != 0 ||
+ strcmp (old_icon, mv->icon) != 0))
+ emit_volume_changed (mv);
+ }
+ g_free (old_name);
+ g_free (old_icon);
+ g_free (old_mount_path);
+}
+
+static void
+hal_changed (HalDevice *device, const char *key, gpointer user_data)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (user_data);
+
+ /*g_warning ("hal modifying %s (property %s changed)", hal_volume->device_path, key);*/
+ update_from_hal (hal_volume, TRUE);
+}
+
+static void
+compute_uuid (GHalVolume *volume)
+{
+ const char *fs_uuid;
+ const char *fs_label;
+
+ /* use the FS uuid before falling back to the FS label */
+
+ fs_uuid = hal_device_get_property_string (volume->device, "volume.uuid");
+ fs_label = hal_device_get_property_string (volume->device, "volume.label");
+
+ if (strlen (fs_uuid) == 0)
+ {
+ if (strlen (fs_label) == 0)
+ volume->uuid = NULL;
+ else
+ volume->uuid = g_strdup (fs_label);
+ }
+ else
+ volume->uuid = g_strdup (fs_uuid);
+}
+
+GHalVolume *
+g_hal_volume_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool,
+ GFile *foreign_mount_root,
+ gboolean is_mountable,
+ GHalDrive *drive)
+{
+ GHalVolume *volume;
+ HalDevice *drive_device;
+ const char *storage_udi;
+ const char *device_path;
+ gboolean ignore_automount;
+
+ ignore_automount = FALSE;
+
+ if (hal_device_has_capability (device, "block"))
+ {
+ storage_udi = hal_device_get_property_string (device, "block.storage_device");
+ if (storage_udi == NULL)
+ return NULL;
+
+ drive_device = hal_pool_get_device_by_udi (pool, storage_udi);
+ if (drive_device == NULL)
+ return NULL;
+
+ device_path = hal_device_get_property_string (device, "block.device");
+ }
+ else
+ {
+ return NULL;
+ }
+
+ if (drive_device &&
+ hal_device_has_property (drive_device, "storage.automount_enabled_hint") &&
+ !hal_device_get_property_bool (drive_device, "storage.automount_enabled_hint"))
+ ignore_automount = TRUE;
+
+ volume = g_object_new (G_TYPE_HAL_VOLUME, NULL);
+ volume->volume_monitor = volume_monitor;
+ g_object_add_weak_pointer (G_OBJECT (volume_monitor), (gpointer) &(volume->volume_monitor));
+ volume->mount_path = NULL;
+ volume->device_path = g_strdup (device_path);
+ volume->device = g_object_ref (device);
+ volume->drive_device = g_object_ref (drive_device);
+ volume->foreign_mount_root = foreign_mount_root != NULL ? g_object_ref (foreign_mount_root) : NULL;
+ volume->is_mountable = is_mountable;
+ volume->ignore_automount = ignore_automount || ! hal_device_is_recently_plugged_in (device);
+
+ g_signal_connect_object (device, "hal_property_changed", (GCallback) hal_changed, volume, 0);
+ g_signal_connect_object (drive_device, "hal_property_changed", (GCallback) hal_changed, volume, 0);
+
+ compute_uuid (volume);
+ update_from_hal (volume, FALSE);
+
+ /* need to do this last */
+ volume->drive = drive;
+ if (drive != NULL)
+ g_hal_drive_set_volume (drive, volume);
+
+ return volume;
+}
+
+/**
+ * g_hal_volume_removed:
+ * @volume:
+ *
+ **/
+void
+g_hal_volume_removed (GHalVolume *volume)
+{
+
+ if (volume->mount != NULL)
+ {
+ g_hal_mount_unset_volume (volume->mount, volume);
+ volume->mount = NULL;
+ }
+
+ if (volume->drive != NULL)
+ {
+ g_hal_drive_unset_volume (volume->drive, volume);
+ volume->drive = NULL;
+ }
+}
+
+void
+g_hal_volume_set_mount (GHalVolume *volume,
+ GHalMount *mount)
+{
+ if (volume->mount != mount)
+ {
+
+ if (volume->mount != NULL)
+ g_hal_mount_unset_volume (volume->mount, volume);
+
+ volume->mount = mount;
+
+ emit_volume_changed (volume);
+ }
+}
+
+void
+g_hal_volume_unset_mount (GHalVolume *volume,
+ GHalMount *mount)
+{
+ if (volume->mount == mount)
+ {
+ volume->mount = NULL;
+ emit_volume_changed (volume);
+ }
+}
+
+void
+g_hal_volume_set_drive (GHalVolume *volume,
+ GHalDrive *drive)
+{
+ if (volume->drive != drive)
+ {
+ if (volume->drive != NULL)
+ g_hal_drive_unset_volume (volume->drive, volume);
+
+ volume->drive = drive;
+
+ emit_volume_changed (volume);
+ }
+}
+
+void
+g_hal_volume_unset_drive (GHalVolume *volume,
+ GHalDrive *drive)
+{
+ if (volume->drive == drive)
+ {
+ volume->drive = NULL;
+ emit_volume_changed (volume);
+ }
+}
+
+static GIcon *
+g_hal_volume_get_icon (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GIcon *icon;
+ const char *name;
+ const char *fallback;
+
+ name = hal_volume->icon;
+
+ if (hal_volume->icon_fallback)
+ fallback = hal_volume->icon_fallback;
+ else /* if no custom fallbacks are set, use the icon to create them */
+ fallback = name;
+
+ icon = get_themed_icon_with_fallbacks (name, fallback);
+ return icon;
+}
+
+static char *
+g_hal_volume_get_name (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+
+ return g_strdup (hal_volume->name);
+}
+
+static char *
+g_hal_volume_get_uuid (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+
+ return g_strdup (hal_volume->uuid);
+}
+
+static gboolean
+g_hal_volume_can_mount (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+
+ return hal_volume->is_mountable;
+}
+
+static gboolean
+g_hal_volume_can_eject (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = FALSE;
+ if (hal_volume->drive != NULL)
+ res = g_drive_can_eject (G_DRIVE (hal_volume->drive));
+
+ return res;
+}
+
+static gboolean
+g_hal_volume_should_automount (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+
+ return ! (hal_volume->ignore_automount);
+}
+
+static GDrive *
+g_hal_volume_get_drive (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GDrive *drive;
+
+ drive = NULL;
+ if (hal_volume->drive != NULL)
+ drive = g_object_ref (hal_volume->drive);
+
+ return drive;
+}
+
+static GMount *
+g_hal_volume_get_mount (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GMount *mount;
+
+ mount = NULL;
+ if (hal_volume->foreign_mount != NULL)
+ mount = g_object_ref (hal_volume->foreign_mount);
+ else if (hal_volume->mount != NULL)
+ mount = g_object_ref (hal_volume->mount);
+
+ return mount;
+}
+
+gboolean
+g_hal_volume_has_mount_path (GHalVolume *volume,
+ const char *mount_path)
+{
+ gboolean res;
+
+ res = FALSE;
+ if (volume->mount_path != NULL)
+ res = strcmp (volume->mount_path, mount_path) == 0;
+
+ return res;
+}
+
+gboolean
+g_hal_volume_has_device_path (GHalVolume *volume,
+ const char *device_path)
+{
+ gboolean res;
+
+ res = FALSE;
+ if (volume->device_path != NULL)
+ res = strcmp (volume->device_path, device_path) == 0;
+ return res;
+}
+
+gboolean
+g_hal_volume_has_udi (GHalVolume *volume,
+ const char *udi)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = FALSE;
+ if (hal_volume->device != NULL)
+ res = strcmp (hal_device_get_udi (hal_volume->device), udi) == 0;
+ return res;
+}
+
+gboolean
+g_hal_volume_has_uuid (GHalVolume *volume,
+ const char *uuid)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = FALSE;
+ if (hal_volume->uuid != NULL)
+ res = strcmp (hal_volume->uuid, uuid) == 0;
+
+ return res;
+}
+
+static void
+foreign_mount_unmounted (GMount *mount, gpointer user_data)
+{
+ GHalVolume *volume = G_HAL_VOLUME (user_data);
+ gboolean check;
+
+ check = volume->foreign_mount == mount;
+ if (check)
+ g_hal_volume_adopt_foreign_mount (volume, NULL);
+}
+
+void
+g_hal_volume_adopt_foreign_mount (GHalVolume *volume, GMount *foreign_mount)
+{
+ if (volume->foreign_mount != NULL)
+ g_object_unref (volume->foreign_mount);
+
+ if (foreign_mount != NULL)
+ {
+ volume->foreign_mount = g_object_ref (foreign_mount);
+ g_signal_connect_object (foreign_mount, "unmounted", (GCallback) foreign_mount_unmounted, volume, 0);
+ }
+ else
+ volume->foreign_mount = NULL;
+
+ emit_volume_changed (volume);
+}
+
+gboolean
+g_hal_volume_has_foreign_mount_root (GHalVolume *volume,
+ GFile *mount_root)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = FALSE;
+ if (hal_volume->foreign_mount_root != NULL)
+ res = g_file_equal (hal_volume->foreign_mount_root, mount_root);
+
+ return res;
+}
+
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
+} SpawnOp;
+
+static void
+spawn_cb (GPid pid, gint status, gpointer user_data)
+{
+ SpawnOp *data = user_data;
+ GSimpleAsyncResult *simple;
+
+ /* ensure that the #GHalMount corrosponding to the #GHalVolume we've
+ * mounted is made available before returning to the user (make sure
+ * we don't emit the signals in idle; see #552168).
+ */
+ g_hal_volume_monitor_force_update (G_HAL_VOLUME_MONITOR (G_HAL_VOLUME (data->object)->volume_monitor), FALSE);
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ GError *error;
+ error = g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_FAILED_HANDLED,
+ "You are not supposed to show G_IO_ERROR_FAILED_HANDLED in the UI");
+ simple = g_simple_async_result_new_from_error (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ }
+ else
+ {
+ simple = g_simple_async_result_new (data->object,
+ data->callback,
+ data->user_data,
+ NULL);
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+spawn_do (GVolume *volume,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ char **argv)
+{
+ SpawnOp *data;
+ GPid child_pid;
+ GError *error;
+
+ data = g_new0 (SpawnOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->cancellable = cancellable;
+
+ error = NULL;
+ if (!g_spawn_async (NULL, /* working dir */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user_data for child_setup */
+ &child_pid,
+ &error))
+ {
+ g_simple_async_report_gerror_in_idle (data->object,
+ data->callback,
+ data->user_data,
+ error);
+ g_object_unref (data->object);
+ g_error_free (error);
+ g_free (data);
+ return;
+ }
+
+ g_child_watch_add (child_pid, spawn_cb, data);
+}
+
+typedef struct
+{
+ GHalVolume *enclosing_volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} ForeignMountOp;
+
+static void
+mount_foreign_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ForeignMountOp *data = user_data;
+ data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data);
+ g_object_unref (data->enclosing_volume);
+ g_free (data);
+}
+
+static void
+g_hal_volume_mount (GVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+
+ /*g_warning ("hal_volume_mount (can_mount=%d foreign=%p device_path=%s)",
+ g_hal_volume_can_mount (volume),
+ hal_volume->foreign_mount_root,
+ hal_volume->device_path);*/
+
+ if (hal_volume->foreign_mount_root != NULL)
+ {
+ ForeignMountOp *data;
+
+ data = g_new0 (ForeignMountOp, 1);
+ data->enclosing_volume = g_object_ref (hal_volume);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ g_file_mount_enclosing_volume (hal_volume->foreign_mount_root,
+ 0,
+ mount_operation,
+ cancellable,
+ mount_foreign_callback,
+ data);
+ }
+ else
+ {
+ char *argv[] = {"gnome-mount", "-b", "-d", NULL, NULL, NULL};
+ argv[3] = hal_volume->device_path;
+ /* ask for no dialogs if mount_operation is NULL */
+ if (mount_operation == NULL)
+ argv[4] = "-n";
+ spawn_do (volume, cancellable, callback, user_data, argv);
+ }
+}
+
+static gboolean
+g_hal_volume_mount_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = TRUE;
+
+ if (hal_volume->foreign_mount_root != NULL)
+ res = g_file_mount_enclosing_volume_finish (hal_volume->foreign_mount_root, result, error);
+
+ return res;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_hal_volume_eject (GVolume *volume,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GHalDrive *drive;
+
+ /*g_warning ("hal_volume_eject");*/
+
+ drive = NULL;
+ if (hal_volume->drive != NULL)
+ drive = g_object_ref (hal_volume->drive);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (G_DRIVE (drive), flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_hal_volume_eject_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ gboolean res;
+
+ res = TRUE;
+ if (hal_volume->drive != NULL)
+ res = g_drive_eject_finish (G_DRIVE (hal_volume->drive), result, error);
+ return res;
+}
+
+static char *
+g_hal_volume_get_identifier (GVolume *volume,
+ const char *kind)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ char *id;
+
+ id = NULL;
+ if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0)
+ id = g_strdup (hal_device_get_udi (hal_volume->device));
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+ id = g_strdup (hal_volume->device_path);
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
+ id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.label"));
+ else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
+ id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.uuid"));
+
+ return id;
+}
+
+static char **
+g_hal_volume_enumerate_identifiers (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GPtrArray *res;
+ const char *label, *uuid;
+
+ res = g_ptr_array_new ();
+
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI));
+
+ if (hal_volume->device_path && *hal_volume->device_path != 0)
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE));
+
+ label = hal_device_get_property_string (hal_volume->device, "volume.label");
+ uuid = hal_device_get_property_string (hal_volume->device, "volume.uuid");
+
+ if (label && *label != 0)
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_LABEL));
+
+ if (uuid && *uuid != 0)
+ g_ptr_array_add (res,
+ g_strdup (G_VOLUME_IDENTIFIER_KIND_UUID));
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **)g_ptr_array_free (res, FALSE);
+}
+
+static GFile *
+g_hal_volume_get_activation_root (GVolume *volume)
+{
+ GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+ GFile *root = NULL;
+
+ if (hal_volume->foreign_mount_root != NULL)
+ root = g_object_ref (hal_volume->foreign_mount_root);
+
+ return root;
+}
+
+static void
+g_hal_volume_volume_iface_init (GVolumeIface *iface)
+{
+ iface->get_name = g_hal_volume_get_name;
+ iface->get_icon = g_hal_volume_get_icon;
+ iface->get_uuid = g_hal_volume_get_uuid;
+ iface->get_drive = g_hal_volume_get_drive;
+ iface->get_mount = g_hal_volume_get_mount;
+ iface->can_mount = g_hal_volume_can_mount;
+ iface->can_eject = g_hal_volume_can_eject;
+ iface->should_automount = g_hal_volume_should_automount;
+ iface->mount_fn = g_hal_volume_mount;
+ iface->mount_finish = g_hal_volume_mount_finish;
+ iface->eject = g_hal_volume_eject;
+ iface->eject_finish = g_hal_volume_eject_finish;
+ iface->get_identifier = g_hal_volume_get_identifier;
+ iface->enumerate_identifiers = g_hal_volume_enumerate_identifiers;
+ iface->get_activation_root = g_hal_volume_get_activation_root;
+}
diff --git a/trunk/monitor/hal/ghalvolume.h b/trunk/monitor/hal/ghalvolume.h
new file mode 100644
index 00000000..edbdfb31
--- /dev/null
+++ b/trunk/monitor/hal/ghalvolume.h
@@ -0,0 +1,84 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_HAL_VOLUME_H__
+#define __G_HAL_VOLUME_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "hal-pool.h"
+#include "ghalvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_HAL_VOLUME (g_hal_volume_get_type ())
+#define G_HAL_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_HAL_VOLUME, GHalVolume))
+#define G_HAL_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_HAL_VOLUME, GHalVolumeClass))
+#define G_IS_HAL_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_HAL_VOLUME))
+#define G_IS_HAL_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_HAL_VOLUME))
+
+typedef struct _GHalVolumeClass GHalVolumeClass;
+
+struct _GHalVolumeClass {
+ GObjectClass parent_class;
+};
+
+GType g_hal_volume_get_type (void) G_GNUC_CONST;
+
+GHalVolume *g_hal_volume_new (GVolumeMonitor *volume_monitor,
+ HalDevice *device,
+ HalPool *pool,
+ GFile *foreign_mount_root,
+ gboolean is_mountable,
+ GHalDrive *drive);
+
+gboolean g_hal_volume_has_mount_path (GHalVolume *volume,
+ const char *mount_path);
+gboolean g_hal_volume_has_device_path (GHalVolume *volume,
+ const char *device_path);
+gboolean g_hal_volume_has_udi (GHalVolume *volume,
+ const char *udi);
+gboolean g_hal_volume_has_uuid (GHalVolume *volume,
+ const char *uuid);
+
+gboolean g_hal_volume_has_foreign_mount_root (GHalVolume *volume,
+ GFile *mount_root);
+
+void g_hal_volume_adopt_foreign_mount (GHalVolume *volume,
+ GMount *foreign_mount);
+
+void g_hal_volume_set_mount (GHalVolume *volume,
+ GHalMount *mount);
+void g_hal_volume_unset_mount (GHalVolume *volume,
+ GHalMount *mount);
+
+void g_hal_volume_set_drive (GHalVolume *volume,
+ GHalDrive *drive);
+void g_hal_volume_unset_drive (GHalVolume *volume,
+ GHalDrive *drive);
+
+void g_hal_volume_removed (GHalVolume *volume);
+
+G_END_DECLS
+
+#endif /* __G_HAL_VOLUME_H__ */
diff --git a/trunk/monitor/hal/ghalvolumemonitor.c b/trunk/monitor/hal/ghalvolumemonitor.c
new file mode 100644
index 00000000..819cd57b
--- /dev/null
+++ b/trunk/monitor/hal/ghalvolumemonitor.c
@@ -0,0 +1,1360 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "ghalvolumemonitor.h"
+#include "ghalmount.h"
+#include "ghalvolume.h"
+#include "ghaldrive.h"
+#include "hal-pool.h"
+
+/* We use this static variable for enforcing a singleton pattern since
+ * the get_mount_for_mount_path() method on GNativeVolumeMonitor calls
+ * us without an instance.. and ideally we want to piggyback on an
+ * already existing instance.
+ *
+ * We don't need locking since this runs out of process in a single
+ * threaded mode with now weird things happening in signal handlers.
+ */
+
+static GHalVolumeMonitor *the_volume_monitor = NULL;
+static HalPool *pool = NULL;
+
+struct _GHalVolumeMonitor {
+ GNativeVolumeMonitor parent;
+
+ GUnixMountMonitor *mount_monitor;
+
+ HalPool *pool;
+
+ GList *last_optical_disc_devices;
+ GList *last_drive_devices;
+ GList *last_volume_devices;
+ GList *last_mountpoints;
+ GList *last_mounts;
+
+ GList *drives;
+ GList *volumes;
+ GList *mounts;
+
+ /* we keep volumes/mounts for blank and audio discs separate to handle e.g. mixed discs properly */
+ GList *disc_volumes;
+ GList *disc_mounts;
+
+};
+
+static void mountpoints_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data);
+static void mounts_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data);
+static void hal_changed (HalPool *pool,
+ HalDevice *device,
+ gpointer user_data);
+static void update_all (GHalVolumeMonitor *monitor,
+ gboolean emit_changes,
+ gboolean emit_in_idle);
+static void update_drives (GHalVolumeMonitor *monitor,
+ GList **added_drives,
+ GList **removed_drives);
+static void update_volumes (GHalVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes);
+static void update_mounts (GHalVolumeMonitor *monitor,
+ GList **added_mounts,
+ GList **removed_mounts);
+static void update_discs (GHalVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes,
+ GList **added_mounts,
+ GList **removed_mounts);
+
+
+G_DEFINE_TYPE (GHalVolumeMonitor, g_hal_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR)
+
+static void
+list_free (GList *objects)
+{
+ g_list_foreach (objects, (GFunc)g_object_unref, NULL);
+ g_list_free (objects);
+}
+
+static HalPool *
+get_hal_pool (void)
+{
+ char *cap_only[] = {"block", NULL};
+
+ if (pool == NULL)
+ pool = hal_pool_new (cap_only);
+
+ return pool;
+}
+
+static void
+g_hal_volume_monitor_dispose (GObject *object)
+{
+ GHalVolumeMonitor *monitor;
+
+ monitor = G_HAL_VOLUME_MONITOR (object);
+
+ the_volume_monitor = NULL;
+
+ if (G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->dispose)
+ (*G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->dispose) (object);
+}
+
+static void
+g_hal_volume_monitor_finalize (GObject *object)
+{
+ GHalVolumeMonitor *monitor;
+
+ monitor = G_HAL_VOLUME_MONITOR (object);
+
+ g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mountpoints_changed, monitor);
+ g_signal_handlers_disconnect_by_func (monitor->mount_monitor, mounts_changed, monitor);
+ g_signal_handlers_disconnect_by_func (monitor->pool, hal_changed, monitor);
+
+ g_object_unref (monitor->mount_monitor);
+ g_object_unref (monitor->pool);
+
+ list_free (monitor->last_optical_disc_devices);
+ list_free (monitor->last_drive_devices);
+ list_free (monitor->last_volume_devices);
+ list_free (monitor->last_mountpoints);
+ g_list_foreach (monitor->last_mounts,
+ (GFunc)g_unix_mount_free, NULL);
+ g_list_free (monitor->last_mounts);
+
+ list_free (monitor->drives);
+ list_free (monitor->volumes);
+ list_free (monitor->mounts);
+
+ list_free (monitor->disc_volumes);
+ list_free (monitor->disc_mounts);
+
+ if (G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize) (object);
+}
+
+static GList *
+get_mounts (GVolumeMonitor *volume_monitor)
+{
+ GHalVolumeMonitor *monitor;
+ GList *l, *ll;
+
+ monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
+
+ l = g_list_copy (monitor->mounts);
+ ll = g_list_copy (monitor->disc_mounts);
+ l = g_list_concat (l, ll);
+
+ g_list_foreach (l, (GFunc)g_object_ref, NULL);
+
+ return l;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+ GHalVolumeMonitor *monitor;
+ GList *l, *ll;
+
+ monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
+
+ l = g_list_copy (monitor->volumes);
+ ll = g_list_copy (monitor->disc_volumes);
+ l = g_list_concat (l, ll);
+
+ g_list_foreach (l, (GFunc)g_object_ref, NULL);
+
+ return l;
+}
+
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
+{
+ GHalVolumeMonitor *monitor;
+ GList *l;
+
+ monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
+
+ l = g_list_copy (monitor->drives);
+ g_list_foreach (l, (GFunc)g_object_ref, NULL);
+
+ return l;
+}
+
+static GVolume *
+get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GHalVolumeMonitor *monitor;
+ GHalVolume *volume;
+ GList *l;
+
+ monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
+
+ volume = NULL;
+
+ for (l = monitor->volumes; l != NULL; l = l->next)
+ {
+ volume = l->data;
+ if (g_hal_volume_has_uuid (volume, uuid))
+ goto found;
+ }
+
+ for (l = monitor->disc_volumes; l != NULL; l = l->next)
+ {
+ volume = l->data;
+ if (g_hal_volume_has_uuid (volume, uuid))
+ goto found;
+ }
+
+ return NULL;
+
+ found:
+
+ g_object_ref (volume);
+
+ return (GVolume *)volume;
+}
+
+static GMount *
+get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GHalVolumeMonitor *monitor;
+ GHalMount *mount;
+ GList *l;
+
+ monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
+
+ mount = NULL;
+
+ for (l = monitor->mounts; l != NULL; l = l->next)
+ {
+ mount = l->data;
+ if (g_hal_mount_has_uuid (mount, uuid))
+ goto found;
+ }
+
+ for (l = monitor->disc_mounts; l != NULL; l = l->next)
+ {
+ mount = l->data;
+ if (g_hal_mount_has_uuid (mount, uuid))
+ goto found;
+ }
+
+ return NULL;
+
+ found:
+
+ g_object_ref (mount);
+
+ return (GMount *)mount;
+}
+
+static GMount *
+get_mount_for_mount_path (const char *mount_path,
+ GCancellable *cancellable)
+{
+ GMount *mount;
+ GHalMount *hal_mount;
+ GHalVolumeMonitor *volume_monitor;
+
+ volume_monitor = NULL;
+ if (the_volume_monitor != NULL)
+ volume_monitor = g_object_ref (the_volume_monitor);
+
+ if (volume_monitor == NULL)
+ {
+ /* Dammit, no monitor is set up.. so we have to create one, find
+ * what the user asks for and throw it away again.
+ *
+ * What a waste - especially considering that there's IO
+ * involved in doing this: connect to the system message bus;
+ * IPC to hald...
+ */
+ volume_monitor = G_HAL_VOLUME_MONITOR (g_hal_volume_monitor_new ());
+ }
+
+ mount = NULL;
+
+ /* creation of the volume monitor might actually fail */
+ if (volume_monitor != NULL)
+ {
+ GList *l;
+
+ for (l = volume_monitor->mounts; l != NULL; l = l->next)
+ {
+ hal_mount = l->data;
+
+ if (g_hal_mount_has_mount_path (hal_mount, mount_path))
+ {
+ mount = g_object_ref (hal_mount);
+ break;
+ }
+ }
+
+ g_object_unref (volume_monitor);
+ }
+
+ return (GMount *)mount;
+}
+
+static void
+mountpoints_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data)
+{
+ GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data);
+
+ update_all (monitor, TRUE, TRUE);
+}
+
+static void
+mounts_changed (GUnixMountMonitor *mount_monitor,
+ gpointer user_data)
+{
+ GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data);
+
+ update_all (monitor, TRUE, TRUE);
+}
+
+void
+g_hal_volume_monitor_force_update (GHalVolumeMonitor *monitor, gboolean emit_in_idle)
+{
+ update_all (monitor, TRUE, emit_in_idle);
+}
+
+static void
+hal_changed (HalPool *pool,
+ HalDevice *device,
+ gpointer user_data)
+{
+ GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data);
+
+ /*g_warning ("hal changed");*/
+
+ update_all (monitor, TRUE, TRUE);
+}
+
+static GObject *
+g_hal_volume_monitor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GHalVolumeMonitor *monitor;
+ GHalVolumeMonitorClass *klass;
+ GObjectClass *parent_class;
+
+ if (the_volume_monitor != NULL)
+ {
+ object = g_object_ref (the_volume_monitor);
+ return object;
+ }
+
+ /*g_warning ("creating hal vm");*/
+
+ object = NULL;
+
+ /* Invoke parent constructor. */
+ klass = G_HAL_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_HAL_VOLUME_MONITOR));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ monitor = G_HAL_VOLUME_MONITOR (object);
+ monitor->pool = g_object_ref (get_hal_pool ());
+
+ monitor->mount_monitor = g_unix_mount_monitor_new ();
+
+ g_signal_connect (monitor->mount_monitor,
+ "mounts_changed", G_CALLBACK (mounts_changed),
+ monitor);
+
+ g_signal_connect (monitor->mount_monitor,
+ "mountpoints_changed", G_CALLBACK (mountpoints_changed),
+ monitor);
+
+ g_signal_connect (monitor->pool,
+ "device_added", G_CALLBACK (hal_changed),
+ monitor);
+
+ g_signal_connect (monitor->pool,
+ "device_removed", G_CALLBACK (hal_changed),
+ monitor);
+
+ update_all (monitor, FALSE, TRUE);
+
+ the_volume_monitor = monitor;
+
+ return object;
+}
+
+static void
+g_hal_volume_monitor_init (GHalVolumeMonitor *monitor)
+{
+}
+
+static gboolean
+is_supported (void)
+{
+ return get_hal_pool() != NULL;
+}
+
+static GVolume *
+adopt_orphan_mount (GMount *mount, GVolumeMonitor *monitor)
+{
+ GList *l;
+ GFile *mount_root;
+ GVolume *ret;
+
+ /* This is called by the union volume monitor which does
+ have a ref to this. So its guaranteed to live, unfortunately
+ the pointer is not passed as an argument :/
+ */
+ ret = NULL;
+
+ if (the_volume_monitor == NULL)
+ {
+ return NULL;
+ }
+
+ mount_root = g_mount_get_root (mount);
+
+ /* cdda:// as foreign mounts */
+ for (l = the_volume_monitor->disc_volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+
+ if (g_hal_volume_has_foreign_mount_root (volume, mount_root))
+ {
+ g_hal_volume_adopt_foreign_mount (volume, mount);
+ ret = g_object_ref (volume);
+ goto found;
+ }
+ }
+
+ found:
+ g_object_unref (mount_root);
+
+ return ret;
+}
+
+static void
+g_hal_volume_monitor_class_init (GHalVolumeMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+ GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass);
+
+ gobject_class->constructor = g_hal_volume_monitor_constructor;
+ gobject_class->finalize = g_hal_volume_monitor_finalize;
+ gobject_class->dispose = g_hal_volume_monitor_dispose;
+
+ monitor_class->get_mounts = get_mounts;
+ monitor_class->get_volumes = get_volumes;
+ monitor_class->get_connected_drives = get_connected_drives;
+ monitor_class->get_volume_for_uuid = get_volume_for_uuid;
+ monitor_class->get_mount_for_uuid = get_mount_for_uuid;
+ monitor_class->adopt_orphan_mount = adopt_orphan_mount;
+ monitor_class->is_supported = is_supported;
+
+ native_class->get_mount_for_mount_path = get_mount_for_mount_path;
+}
+
+/**
+ * g_hal_volume_monitor_new:
+ *
+ * Returns: a new #GVolumeMonitor.
+ **/
+GVolumeMonitor *
+g_hal_volume_monitor_new (void)
+{
+ GHalVolumeMonitor *monitor;
+
+ monitor = g_object_new (G_TYPE_HAL_VOLUME_MONITOR, NULL);
+
+ return G_VOLUME_MONITOR (monitor);
+}
+
+static void
+diff_sorted_lists (GList *list1,
+ GList *list2,
+ GCompareFunc compare,
+ GList **added,
+ GList **removed)
+{
+ int order;
+
+ *added = *removed = NULL;
+
+ while (list1 != NULL &&
+ list2 != NULL)
+ {
+ order = (*compare) (list1->data, list2->data);
+ if (order < 0)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ else if (order > 0)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+ else
+ { /* same item */
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+ }
+
+ while (list1 != NULL)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ while (list2 != NULL)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+}
+
+static GHalVolume *
+lookup_volume_for_mount_path (GHalVolumeMonitor *monitor,
+ const char *mount_path)
+{
+ GList *l;
+ GHalVolume *found;
+
+ found = NULL;
+
+ for (l = monitor->volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+
+ if (g_hal_volume_has_mount_path (volume, mount_path))
+ {
+ found = volume;
+ break;
+ }
+ }
+
+ return found;
+}
+
+static GHalVolume *
+lookup_volume_for_device_path (GHalVolumeMonitor *monitor,
+ const char *device_path)
+{
+ GList *l;
+
+ for (l = monitor->volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+
+ if (g_hal_volume_has_device_path (volume, device_path))
+ return volume;
+ }
+
+ return NULL;
+}
+
+
+
+static GHalMount *
+find_mount_by_mount_path (GHalVolumeMonitor *monitor,
+ const char *mount_path)
+{
+ GList *l;
+
+ for (l = monitor->mounts; l != NULL; l = l->next)
+ {
+ GHalMount *mount = l->data;
+
+ if (g_hal_mount_has_mount_path (mount, mount_path))
+ return mount;
+ }
+
+ return NULL;
+}
+
+static GHalVolume *
+find_volume_by_udi (GHalVolumeMonitor *monitor, const char *udi)
+{
+ GList *l;
+
+ for (l = monitor->volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+
+ if (g_hal_volume_has_udi (volume, udi))
+ return volume;
+ }
+
+ return NULL;
+}
+
+static GHalDrive *
+find_drive_by_udi (GHalVolumeMonitor *monitor, const char *udi)
+{
+ GList *l;
+
+ for (l = monitor->drives; l != NULL; l = l->next)
+ {
+ GHalDrive *drive = l->data;
+
+ if (g_hal_drive_has_udi (drive, udi))
+ return drive;
+ }
+
+ return NULL;
+}
+
+static GHalMount *
+find_disc_mount_by_udi (GHalVolumeMonitor *monitor, const char *udi)
+{
+ GList *l;
+
+ for (l = monitor->disc_mounts; l != NULL; l = l->next)
+ {
+ GHalMount *mount = l->data;
+
+ if (g_hal_mount_has_udi (mount, udi))
+ return mount;
+ }
+
+ return NULL;
+}
+
+static GHalVolume *
+find_disc_volume_by_udi (GHalVolumeMonitor *monitor, const char *udi)
+{
+ GList *l;
+
+ for (l = monitor->disc_volumes; l != NULL; l = l->next)
+ {
+ GHalVolume *volume = l->data;
+
+ if (g_hal_volume_has_udi (volume, udi))
+ return volume;
+ }
+
+ return NULL;
+}
+
+static gint
+hal_device_compare (HalDevice *a, HalDevice *b)
+{
+ return strcmp (hal_device_get_udi (a), hal_device_get_udi (b));
+}
+
+/* TODO: move to gio */
+static gboolean
+_g_unix_mount_point_guess_should_display (GUnixMountPoint *mount_point)
+{
+ const char *mount_path;
+
+ mount_path = g_unix_mount_point_get_mount_path (mount_point);
+
+ /* Never display internal mountpoints */
+ if (g_unix_is_mount_path_system_internal (mount_path))
+ return FALSE;
+
+ /* Only display things in /media (which are generally user mountable)
+ and home dir (fuse stuff) */
+ if (g_str_has_prefix (mount_path, "/media/"))
+ return TRUE;
+
+ if (g_str_has_prefix (mount_path, g_get_home_dir ()))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static GUnixMountPoint *
+get_mount_point_for_device (HalDevice *d, GList *fstab_mount_points)
+{
+ GList *l;
+ const char *device_file;
+ const char *device_mount_point;
+
+ device_mount_point = hal_device_get_property_string (d, "volume.mount_point");
+
+ device_file = hal_device_get_property_string (d, "block.device");
+
+ for (l = fstab_mount_points; l != NULL; l = l->next)
+ {
+ GUnixMountPoint *mount_point = l->data;
+ const char *device_path;
+ const char *mount_path;
+
+ mount_path = g_unix_mount_point_get_mount_path (mount_point);
+ if (device_mount_point != NULL &&
+ mount_path != NULL &&
+ strcmp (device_mount_point, mount_path) == 0)
+ return mount_point;
+
+ device_path = g_unix_mount_point_get_device_path (mount_point);
+ if (g_str_has_prefix (device_path, "LABEL="))
+ {
+ if (strcmp (device_path + 6, hal_device_get_property_string (d, "volume.label")) == 0)
+ return mount_point;
+ }
+ else if (g_str_has_prefix (device_path, "UUID="))
+ {
+ if (g_ascii_strcasecmp (device_path + 5, hal_device_get_property_string (d, "volume.uuid")) == 0)
+ return mount_point;
+ }
+ else
+ {
+ char resolved_device_path[PATH_MAX];
+ /* handle symlinks such as /dev/disk/by-uuid/47C2-1994 */
+ if (realpath (device_path, resolved_device_path) != NULL &&
+ strcmp (resolved_device_path, device_file) == 0)
+ return mount_point;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean
+should_mount_be_ignored (HalPool *pool, HalDevice *d)
+{
+ const char *device_mount_point;
+
+ device_mount_point = hal_device_get_property_string (d, "volume.mount_point");
+ if (device_mount_point != NULL && strlen (device_mount_point) > 0)
+ {
+ GUnixMountEntry *mount_entry;
+
+ /*g_warning ("device_mount_point = '%s'", device_mount_point);*/
+
+ mount_entry = g_unix_mount_at (device_mount_point, NULL);
+ if (mount_entry != NULL) {
+ if (!g_unix_mount_guess_should_display (mount_entry))
+ {
+ g_unix_mount_free (mount_entry);
+ return TRUE;
+ }
+ g_unix_mount_free (mount_entry);
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+should_volume_be_ignored (HalPool *pool, HalDevice *d, GList *fstab_mount_points)
+{
+ gboolean volume_ignore;
+ const char *volume_fsusage;
+ GUnixMountPoint *mount_point;
+
+ volume_fsusage = hal_device_get_property_string (d, "volume.fsusage");
+ volume_ignore = hal_device_get_property_bool (d, "volume.ignore");
+
+ if (volume_fsusage == NULL)
+ {
+ /*g_warning ("no volume.fsusage property. Refusing to ignore");*/
+ return FALSE;
+ }
+
+ if (volume_ignore)
+ return TRUE;
+
+ if (strcmp (volume_fsusage, "filesystem") != 0)
+ {
+ /* no file system on the volume... blank and audio discs are handled in update_discs() */
+
+ /* check if it's a LUKS crypto volume */
+ if (strcmp (volume_fsusage, "crypto") == 0)
+ {
+ if (strcmp (hal_device_get_property_string (d, "volume.fstype"), "crypto_LUKS") == 0)
+ {
+ HalDevice *cleartext_device;
+
+ /* avoid showing cryptotext volume if it's corresponding cleartext volume is available */
+ cleartext_device = hal_pool_get_device_by_capability_and_string (pool,
+ "block",
+ "volume.crypto_luks.clear.backing_volume",
+ hal_device_get_udi (d));
+
+ if (cleartext_device == NULL)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+
+ mount_point = get_mount_point_for_device (d, fstab_mount_points);
+ if (mount_point != NULL && !_g_unix_mount_point_guess_should_display (mount_point))
+ return TRUE;
+
+ if (hal_device_get_property_bool (d, "volume.is_mounted"))
+ return should_mount_be_ignored (pool, d);
+
+ return FALSE;
+}
+
+static gboolean
+should_drive_be_ignored (HalPool *pool, HalDevice *d, GList *fstab_mount_points)
+{
+ GList *volumes, *l;
+ const char *drive_udi;
+ gboolean all_volumes_ignored, got_volumes;
+
+ /* never ignore drives with removable media */
+ if (hal_device_get_property_bool (d, "storage.removable"))
+ return FALSE;
+
+ drive_udi = hal_device_get_udi (d);
+
+ volumes = hal_pool_find_by_capability (pool, "volume");
+
+ all_volumes_ignored = TRUE;
+ got_volumes = FALSE;
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ HalDevice *volume_dev = l->data;
+ if (strcmp (drive_udi, hal_device_get_property_string (volume_dev, "block.storage_device")) == 0)
+ {
+ got_volumes = TRUE;
+ if (!should_volume_be_ignored (pool, volume_dev, fstab_mount_points) ||
+ hal_device_get_property_bool (volume_dev, "volume.disc.has_audio") ||
+ hal_device_get_property_bool (volume_dev, "volume.disc.is_blank"))
+ {
+ all_volumes_ignored = FALSE;
+ break;
+ }
+ }
+ }
+
+ return got_volumes && all_volumes_ignored;
+}
+
+static void
+list_emit (GHalVolumeMonitor *monitor,
+ const char *monitor_signal,
+ const char *object_signal,
+ GList *objects)
+{
+ GList *l;
+
+ for (l = objects; l != NULL; l = l->next)
+ {
+ g_signal_emit_by_name (monitor, monitor_signal, l->data);
+ if (object_signal)
+ g_signal_emit_by_name (l->data, object_signal);
+ }
+}
+
+typedef struct {
+ GHalVolumeMonitor *monitor;
+ GList *added_drives, *removed_drives;
+ GList *added_volumes, *removed_volumes;
+ GList *added_mounts, *removed_mounts;
+} ChangedLists;
+
+
+static gboolean
+emit_lists_in_idle (gpointer data)
+{
+ ChangedLists *lists = data;
+
+ list_emit (lists->monitor,
+ "drive_disconnected", NULL,
+ lists->removed_drives);
+ list_emit (lists->monitor,
+ "drive_connected", NULL,
+ lists->added_drives);
+
+ list_emit (lists->monitor,
+ "volume_removed", "removed",
+ lists->removed_volumes);
+ list_emit (lists->monitor,
+ "volume_added", NULL,
+ lists->added_volumes);
+
+ list_emit (lists->monitor,
+ "mount_removed", "unmounted",
+ lists->removed_mounts);
+ list_emit (lists->monitor,
+ "mount_added", NULL,
+ lists->added_mounts);
+
+ list_free (lists->removed_drives);
+ list_free (lists->added_drives);
+ list_free (lists->removed_volumes);
+ list_free (lists->added_volumes);
+ list_free (lists->removed_mounts);
+ list_free (lists->added_mounts);
+ g_object_unref (lists->monitor);
+ g_free (lists);
+
+ return FALSE;
+}
+
+/* Must be called from idle if emit_changes, with no locks held */
+static void
+update_all (GHalVolumeMonitor *monitor,
+ gboolean emit_changes,
+ gboolean emit_in_idle)
+{
+ ChangedLists *lists;
+ GList *added_drives, *removed_drives;
+ GList *added_volumes, *removed_volumes;
+ GList *added_mounts, *removed_mounts;
+
+ added_drives = NULL;
+ removed_drives = NULL;
+ added_volumes = NULL;
+ removed_volumes = NULL;
+ added_mounts = NULL;
+ removed_mounts = NULL;
+
+ update_drives (monitor, &added_drives, &removed_drives);
+ update_volumes (monitor, &added_volumes, &removed_volumes);
+ update_mounts (monitor, &added_mounts, &removed_mounts);
+ update_discs (monitor,
+ &added_volumes, &removed_volumes,
+ &added_mounts, &removed_mounts);
+
+ if (emit_changes)
+ {
+ lists = g_new0 (ChangedLists, 1);
+ lists->monitor = g_object_ref (monitor);
+ lists->added_drives = added_drives;
+ lists->removed_drives = removed_drives;
+ lists->added_volumes = added_volumes;
+ lists->removed_volumes = removed_volumes;
+ lists->added_mounts = added_mounts;
+ lists->removed_mounts = removed_mounts;
+
+ if (emit_in_idle)
+ g_idle_add (emit_lists_in_idle, lists);
+ else
+ emit_lists_in_idle (lists);
+ }
+ else
+ {
+ list_free (removed_drives);
+ list_free (added_drives);
+ list_free (removed_volumes);
+ list_free (added_volumes);
+ list_free (removed_mounts);
+ list_free (added_mounts);
+ }
+}
+
+static void
+update_drives (GHalVolumeMonitor *monitor,
+ GList **added_drives,
+ GList **removed_drives)
+{
+ GList *new_drive_devices;
+ GList *removed, *added;
+ GList *l, *ll;
+ GHalDrive *drive;
+ GList *fstab_mount_points;
+
+ fstab_mount_points = g_unix_mount_points_get (NULL);
+
+ new_drive_devices = hal_pool_find_by_capability (monitor->pool, "storage");
+
+ /* remove devices we want to ignore - we do it here so we get to reevaluate
+ * on the next update whether they should still be ignored
+ */
+ for (l = new_drive_devices; l != NULL; l = ll)
+ {
+ HalDevice *d = l->data;
+ ll = l->next;
+ if (should_drive_be_ignored (monitor->pool, d, fstab_mount_points))
+ new_drive_devices = g_list_delete_link (new_drive_devices, l);
+ }
+
+ g_list_foreach (new_drive_devices, (GFunc) g_object_ref, NULL);
+
+ new_drive_devices = g_list_sort (new_drive_devices, (GCompareFunc) hal_device_compare);
+ diff_sorted_lists (monitor->last_drive_devices,
+ new_drive_devices, (GCompareFunc) hal_device_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ drive = find_drive_by_udi (monitor, hal_device_get_udi (d));
+ if (drive != NULL)
+ {
+ /*g_warning ("hal removing drive %s", hal_device_get_property_string (d, "block.device"));*/
+ g_hal_drive_disconnected (drive);
+ monitor->drives = g_list_remove (monitor->drives, drive);
+ *removed_drives = g_list_prepend (*removed_drives, drive);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ drive = find_drive_by_udi (monitor, hal_device_get_udi (d));
+ if (drive == NULL)
+ {
+ /*g_warning ("hal adding drive %s", hal_device_get_property_string (d, "block.device"));*/
+ drive = g_hal_drive_new (G_VOLUME_MONITOR (monitor), d, monitor->pool);
+ if (drive != NULL)
+ {
+ monitor->drives = g_list_prepend (monitor->drives, drive);
+ *added_drives = g_list_prepend (*added_drives, g_object_ref (drive));
+ }
+ }
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+ list_free (monitor->last_drive_devices);
+ monitor->last_drive_devices = new_drive_devices;
+
+ g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL);
+ g_list_free (fstab_mount_points);
+}
+
+static void
+update_volumes (GHalVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes)
+{
+ GList *new_volume_devices;
+ GList *removed, *added;
+ GList *l, *ll;
+ GHalVolume *volume;
+ GHalDrive *drive;
+ GList *fstab_mount_points;
+
+ fstab_mount_points = g_unix_mount_points_get (NULL);
+
+ new_volume_devices = hal_pool_find_by_capability (monitor->pool, "volume");
+
+ /* remove devices we want to ignore - we do it here so we get to reevaluate
+ * on the next update whether they should still be ignored
+ */
+ for (l = new_volume_devices; l != NULL; l = ll)
+ {
+ HalDevice *d = l->data;
+ ll = l->next;
+ if (should_volume_be_ignored (monitor->pool, d, fstab_mount_points))
+ new_volume_devices = g_list_delete_link (new_volume_devices, l);
+ }
+
+ g_list_foreach (new_volume_devices, (GFunc) g_object_ref, NULL);
+
+ new_volume_devices = g_list_sort (new_volume_devices, (GCompareFunc) hal_device_compare);
+ diff_sorted_lists (monitor->last_volume_devices,
+ new_volume_devices, (GCompareFunc) hal_device_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ volume = find_volume_by_udi (monitor, hal_device_get_udi (d));
+ if (volume != NULL)
+ {
+ /*g_warning ("hal removing vol %s", hal_device_get_property_string (d, "block.device"));*/
+ g_hal_volume_removed (volume);
+ monitor->volumes = g_list_remove (monitor->volumes, volume);
+
+ *removed_volumes = g_list_prepend (*removed_volumes, volume);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ volume = find_volume_by_udi (monitor, hal_device_get_udi (d));
+ if (volume == NULL)
+ {
+ drive = find_drive_by_udi (monitor, hal_device_get_property_string (d, "block.storage_device"));
+
+ /*g_warning ("hal adding vol %s (drive %p)", hal_device_get_property_string (d, "block.device"), drive);*/
+ volume = g_hal_volume_new (G_VOLUME_MONITOR (monitor),
+ d,
+ monitor->pool,
+ NULL,
+ TRUE,
+ drive);
+ if (volume != NULL)
+ {
+ monitor->volumes = g_list_prepend (monitor->volumes, volume);
+ *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+ }
+ }
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+ list_free (monitor->last_volume_devices);
+ monitor->last_volume_devices = new_volume_devices;
+
+ g_list_foreach (fstab_mount_points, (GFunc) g_unix_mount_point_free, NULL);
+ g_list_free (fstab_mount_points);
+}
+
+static void
+update_mounts (GHalVolumeMonitor *monitor,
+ GList **added_mounts,
+ GList **removed_mounts)
+{
+ GList *new_mounts;
+ GList *removed, *added;
+ GList *l, *ll;
+ GHalMount *mount;
+ GHalVolume *volume;
+ const char *device_path;
+ const char *mount_path;
+
+ new_mounts = g_unix_mounts_get (NULL);
+
+ /* remove mounts we want to ignore - we do it here so we get to reevaluate
+ * on the next update whether they should still be ignored
+ */
+ for (l = new_mounts; l != NULL; l = ll)
+ {
+ GUnixMountEntry *mount_entry = l->data;
+ ll = l->next;
+
+ /* keep in sync with should_mount_be_ignored() */
+ if (!g_unix_mount_guess_should_display (mount_entry))
+ {
+ g_unix_mount_free (mount_entry);
+ new_mounts = g_list_delete_link (new_mounts, l);
+ }
+ }
+
+ new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare);
+
+ diff_sorted_lists (monitor->last_mounts,
+ new_mounts, (GCompareFunc) g_unix_mount_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ GUnixMountEntry *mount_entry = l->data;
+
+ mount = find_mount_by_mount_path (monitor, g_unix_mount_get_mount_path (mount_entry));
+ /*g_warning ("hal removing mount %s (%p)", g_unix_mount_get_device_path (mount_entry), mount);*/
+ if (mount)
+ {
+ g_hal_mount_unmounted (mount);
+ monitor->mounts = g_list_remove (monitor->mounts, mount);
+
+ *removed_mounts = g_list_prepend (*removed_mounts, mount);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ GUnixMountEntry *mount_entry = l->data;
+
+ device_path = g_unix_mount_get_device_path (mount_entry);
+ mount_path = g_unix_mount_get_mount_path (mount_entry);
+ volume = lookup_volume_for_device_path (monitor, device_path);
+ if (volume == NULL)
+ volume = lookup_volume_for_mount_path (monitor, mount_path);
+
+ /*g_warning ("hal adding mount %s (vol %p)", g_unix_mount_get_device_path (mount_entry), volume);*/
+ mount = g_hal_mount_new (G_VOLUME_MONITOR (monitor), mount_entry, monitor->pool, volume);
+ if (mount)
+ {
+ monitor->mounts = g_list_prepend (monitor->mounts, mount);
+ *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount));
+ }
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+ g_list_foreach (monitor->last_mounts,
+ (GFunc)g_unix_mount_free, NULL);
+ g_list_free (monitor->last_mounts);
+ monitor->last_mounts = new_mounts;
+}
+
+static void
+update_discs (GHalVolumeMonitor *monitor,
+ GList **added_volumes,
+ GList **removed_volumes,
+ GList **added_mounts,
+ GList **removed_mounts)
+{
+ GList *new_optical_disc_devices;
+ GList *removed, *added;
+ GList *l, *ll;
+ GHalDrive *drive;
+ GHalVolume *volume;
+ GHalMount *mount;
+ const char *udi;
+ const char *drive_udi;
+
+ /* we also need to generate GVolume + GMount objects for
+ *
+ * - optical discs that have audio
+ * - optical discs that are blank
+ *
+ */
+
+ new_optical_disc_devices = hal_pool_find_by_capability (monitor->pool, "volume.disc");
+ for (l = new_optical_disc_devices; l != NULL; l = ll)
+ {
+ HalDevice *d = l->data;
+ ll = l->next;
+ if (! (hal_device_get_property_bool (d, "volume.disc.is_blank") ||
+ hal_device_get_property_bool (d, "volume.disc.has_audio")))
+ {
+ /* filter out everything but discs that are blank or has audio */
+ new_optical_disc_devices = g_list_delete_link (new_optical_disc_devices, l);
+ }
+ }
+
+ g_list_foreach (new_optical_disc_devices, (GFunc) g_object_ref, NULL);
+
+ new_optical_disc_devices = g_list_sort (new_optical_disc_devices, (GCompareFunc) hal_device_compare);
+ diff_sorted_lists (monitor->last_optical_disc_devices,
+ new_optical_disc_devices, (GCompareFunc) hal_device_compare,
+ &added, &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ udi = hal_device_get_udi (d);
+ /*g_warning ("audio/blank disc removing %s", udi);*/
+
+ mount = find_disc_mount_by_udi (monitor, udi);
+ if (mount != NULL)
+ {
+ g_hal_mount_unmounted (mount);
+ monitor->disc_mounts = g_list_remove (monitor->disc_mounts, mount);
+ *removed_mounts = g_list_prepend (*removed_mounts, mount);
+ }
+
+ volume = find_disc_volume_by_udi (monitor, udi);
+ if (volume != NULL)
+ {
+ g_hal_volume_removed (volume);
+ monitor->disc_volumes = g_list_remove (monitor->disc_volumes, volume);
+ *removed_volumes = g_list_prepend (*removed_volumes, volume);
+ }
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ HalDevice *d = l->data;
+
+ udi = hal_device_get_udi (d);
+ /*g_warning ("audio/blank disc adding %s", udi);*/
+
+ drive_udi = hal_device_get_property_string (d, "block.storage_device");
+ drive = find_drive_by_udi (monitor, drive_udi);
+ if (drive != NULL)
+ {
+ mount = NULL;
+ if (hal_device_get_property_bool (d, "volume.disc.is_blank"))
+ {
+ volume = g_hal_volume_new (G_VOLUME_MONITOR (monitor),
+ d, monitor->pool,
+ NULL,
+ FALSE,
+ drive);
+ if (volume != NULL)
+ {
+ GFile *root;
+ root = g_file_new_for_uri ("burn:///");
+ mount = g_hal_mount_new_for_hal_device (G_VOLUME_MONITOR (monitor),
+ d,
+ root,
+ NULL,
+ NULL,
+ TRUE,
+ monitor->pool,
+ volume);
+ g_object_unref (root);
+ }
+ }
+ else
+ {
+ char *uri;
+ char *device_basename;
+ GFile *foreign_mount_root;
+
+ /* the gvfsd-cdda backend uses URI's like these */
+ device_basename = g_path_get_basename (hal_device_get_property_string (d, "block.device"));
+ uri = g_strdup_printf ("cdda://%s", device_basename);
+ foreign_mount_root = g_file_new_for_uri (uri);
+ g_free (device_basename);
+ g_free (uri);
+
+ volume = g_hal_volume_new (G_VOLUME_MONITOR (monitor),
+ d,
+ monitor->pool,
+ foreign_mount_root,
+ TRUE,
+ drive);
+ g_object_unref (foreign_mount_root);
+ mount = NULL;
+ }
+
+ if (volume != NULL)
+ {
+ monitor->disc_volumes = g_list_prepend (monitor->disc_volumes, volume);
+ *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+
+ if (mount != NULL)
+ {
+ monitor->disc_mounts = g_list_prepend (monitor->disc_mounts, mount);
+ *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount));
+ }
+ }
+ }
+ }
+
+ g_list_free (added);
+ g_list_free (removed);
+ list_free (monitor->last_optical_disc_devices);
+ monitor->last_optical_disc_devices = new_optical_disc_devices;
+}
diff --git a/trunk/monitor/hal/ghalvolumemonitor.h b/trunk/monitor/hal/ghalvolumemonitor.h
new file mode 100644
index 00000000..ad45af38
--- /dev/null
+++ b/trunk/monitor/hal/ghalvolumemonitor.h
@@ -0,0 +1,59 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_HAL_VOLUME_MONITOR_H__
+#define __G_HAL_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_HAL_VOLUME_MONITOR (g_hal_volume_monitor_get_type ())
+#define G_HAL_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_HAL_VOLUME_MONITOR, GHalVolumeMonitor))
+#define G_HAL_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_HAL_VOLUME_MONITOR, GHalVolumeMonitorClass))
+#define G_IS_HAL_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_HAL_VOLUME_MONITOR))
+#define G_IS_HAL_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_HAL_VOLUME_MONITOR))
+
+typedef struct _GHalVolumeMonitor GHalVolumeMonitor;
+typedef struct _GHalVolumeMonitorClass GHalVolumeMonitorClass;
+
+/* Forward definitions */
+typedef struct _GHalDrive GHalDrive;
+typedef struct _GHalVolume GHalVolume;
+typedef struct _GHalMount GHalMount;
+
+struct _GHalVolumeMonitorClass {
+ GNativeVolumeMonitorClass parent_class;
+
+};
+
+GType g_hal_volume_monitor_get_type (void) G_GNUC_CONST;
+
+GVolumeMonitor *g_hal_volume_monitor_new (void);
+void g_hal_volume_monitor_force_update (GHalVolumeMonitor *monitor,
+ gboolean emit_in_idle);
+
+G_END_DECLS
+
+#endif /* __G_HAL_VOLUME_MONITOR_H__ */
diff --git a/trunk/monitor/hal/hal-device.c b/trunk/monitor/hal/hal-device.c
new file mode 100644
index 00000000..9f0b5bc3
--- /dev/null
+++ b/trunk/monitor/hal/hal-device.c
@@ -0,0 +1,297 @@
+/* hal-device.c
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include "hal-device.h"
+#include "hal-marshal.h"
+
+struct _HalDevicePrivate
+{
+ LibHalContext *hal_ctx;
+ LibHalPropertySet *properties;
+ char *udi;
+ GTimeVal time_added;
+};
+
+enum {
+ HAL_PROPERTY_CHANGED,
+ HAL_CONDITION,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (HalDevice, hal_device, G_TYPE_OBJECT)
+
+static void
+hal_device_finalize (HalDevice *device)
+{
+ if (device->priv->properties != NULL)
+ libhal_free_property_set (device->priv->properties);
+ g_free (device->priv->udi);
+
+ if (G_OBJECT_CLASS (hal_device_parent_class)->finalize)
+ (* G_OBJECT_CLASS (hal_device_parent_class)->finalize) (G_OBJECT (device));
+}
+
+static void
+hal_device_class_init (HalDeviceClass *klass)
+{
+ GObjectClass *obj_class = (GObjectClass *) klass;
+
+ obj_class->finalize = (GObjectFinalizeFunc) hal_device_finalize;
+
+ signals[HAL_PROPERTY_CHANGED] =
+ g_signal_new ("hal_property_changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, hal_property_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ signals[HAL_CONDITION] =
+ g_signal_new ("hal_condition",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, hal_condition),
+ NULL, NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+}
+
+static void
+hal_device_init (HalDevice *device)
+{
+ device->priv = g_new0 (HalDevicePrivate, 1);
+ g_get_current_time (&(device->priv->time_added));
+}
+
+const char *
+hal_device_get_property_string (HalDevice *device, const char *key)
+{
+ const char *ret;
+
+ ret = libhal_ps_get_string (device->priv->properties, key);
+ if (ret != NULL)
+ return ret;
+
+ /* play it safe and don't make clients crash */
+ return "";
+}
+
+int
+hal_device_get_property_int (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_int32 (device->priv->properties, key);
+}
+
+double
+hal_device_get_property_double (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_double (device->priv->properties, key);
+}
+
+guint64
+hal_device_get_property_uint64 (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_uint64 (device->priv->properties, key);
+}
+
+gboolean
+hal_device_get_property_bool (HalDevice *device, const char *key)
+{
+ return libhal_ps_get_bool (device->priv->properties, key);
+}
+
+char **
+hal_device_get_property_strlist (HalDevice *device, const char *key)
+{
+ static char * empty[1] = {NULL};
+ char **ret;
+
+ ret = (char **) libhal_ps_get_strlist (device->priv->properties, key);
+ if (ret != NULL)
+ return (char **) ret;
+
+ /* play it safe and don't make clients crash */
+ return empty;
+}
+
+gboolean
+hal_device_has_capability (HalDevice *device, const char *capability)
+{
+ int n;
+ char **caps;
+ gboolean ret;
+
+ ret = FALSE;
+ caps = hal_device_get_property_strlist (device, "info.capabilities");
+ if (caps == NULL)
+ goto out;
+
+ for (n = 0; caps[n] != NULL; n++)
+ {
+ if (g_ascii_strcasecmp (caps[n], capability) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+gboolean
+hal_device_has_interface (HalDevice *device, const char *interface)
+{
+ int n;
+ char **ifs;
+ gboolean ret;
+
+ ret = FALSE;
+ ifs = hal_device_get_property_strlist (device, "info.interfaces");
+ if (ifs == NULL)
+ goto out;
+
+ for (n = 0; ifs[n] != NULL; n++)
+ {
+ if (g_ascii_strcasecmp (ifs[n], interface) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+out:
+ return ret;
+}
+
+gboolean
+hal_device_has_property (HalDevice *device, const char *key)
+{
+ gboolean ret;
+ LibHalPropertySetIterator it;
+
+ ret = FALSE;
+ if (device->priv->properties == NULL)
+ goto out;
+
+ libhal_psi_init (&it, device->priv->properties);
+
+ while (libhal_psi_has_more (&it))
+ {
+ char *pkey = libhal_psi_get_key (&it);
+
+ if (pkey != NULL && g_ascii_strcasecmp (pkey, key) == 0)
+ {
+ ret = TRUE;
+ break;
+ }
+ libhal_psi_next (&it);
+ }
+
+ out:
+ return ret;
+}
+
+
+HalDevice *
+hal_device_new_from_udi (LibHalContext *hal_ctx, const char *udi)
+{
+ HalDevice *device;
+
+ device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
+ device->priv->udi = g_strdup (udi);
+ device->priv->hal_ctx = hal_ctx;
+ device->priv->properties = libhal_device_get_all_properties (hal_ctx, udi, NULL);
+ return device;
+}
+
+HalDevice *
+hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx,
+ char *udi,
+ LibHalPropertySet *properties)
+{
+ HalDevice *device;
+
+ device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
+ device->priv->udi = g_strdup (udi);
+ device->priv->hal_ctx = hal_ctx;
+ device->priv->properties = properties;
+ return device;
+}
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key);
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail);
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key)
+{
+ LibHalPropertySet *new_props;
+
+ new_props = libhal_device_get_all_properties (device->priv->hal_ctx, device->priv->udi, NULL);
+ if (new_props != NULL)
+ {
+ libhal_free_property_set (device->priv->properties);
+ device->priv->properties = new_props;
+ g_signal_emit (device, signals[HAL_PROPERTY_CHANGED], 0, key);
+ }
+}
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail)
+{
+ g_signal_emit (device, signals[HAL_CONDITION], 0, name, detail);
+}
+
+const char *
+hal_device_get_udi (HalDevice *device)
+{
+ return device->priv->udi;
+}
+
+LibHalPropertySet *
+hal_device_get_properties (HalDevice *device)
+{
+ return device->priv->properties;
+}
+
+gboolean
+hal_device_is_recently_plugged_in (HalDevice *device)
+{
+ GTimeVal now;
+ glong delta_msec;
+
+ g_get_current_time (&now);
+
+ delta_msec = (now.tv_sec - device->priv->time_added.tv_sec) * 1000 +
+ (now.tv_usec - device->priv->time_added.tv_usec) / 1000;
+
+ return delta_msec < 2000;
+}
diff --git a/trunk/monitor/hal/hal-device.h b/trunk/monitor/hal/hal-device.h
new file mode 100644
index 00000000..8e91aa63
--- /dev/null
+++ b/trunk/monitor/hal/hal-device.h
@@ -0,0 +1,93 @@
+/* hal-device.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef HAL_DEVICE_H
+#define HAL_DEVICE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <libhal.h>
+
+#define HAL_TYPE_DEVICE (hal_device_get_type ())
+#define HAL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_DEVICE, HalDevice))
+#define HAL_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_DEVICE, HalDeviceClass))
+#define HAL_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_DEVICE))
+#define HAL_IS_DEVICE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_DEVICE))
+#define HAL_DEVICE_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_DEVICE, HalDeviceClass))
+
+
+typedef struct _HalDevice HalDevice;
+typedef struct _HalDeviceClass HalDeviceClass;
+
+struct _HalDevicePrivate;
+typedef struct _HalDevicePrivate HalDevicePrivate;
+
+struct _HalDevice
+{
+ GObject parent;
+
+ /* private */
+ HalDevicePrivate *priv;
+};
+
+struct _HalDeviceClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*hal_property_changed) (HalDevice *device, const char *key);
+ void (*hal_condition) (HalDevice *device, const char *name, const char *detail);
+};
+
+
+GType hal_device_get_type (void);
+
+HalDevice * hal_device_new_from_udi (LibHalContext *hal_ctx,
+ const char *udi);
+
+HalDevice * hal_device_new_from_udi_and_properties (LibHalContext *hal_ctx,
+ char *udi,
+ LibHalPropertySet *properties);
+
+const char * hal_device_get_udi (HalDevice *device);
+LibHalPropertySet * hal_device_get_properties (HalDevice *device);
+const char * hal_device_get_property_string (HalDevice *device,
+ const char *key);
+int hal_device_get_property_int (HalDevice *device,
+ const char *key);
+guint64 hal_device_get_property_uint64 (HalDevice *device,
+ const char *key);
+double hal_device_get_property_double (HalDevice *device,
+ const char *key);
+gboolean hal_device_get_property_bool (HalDevice *device,
+ const char *key);
+char ** hal_device_get_property_strlist (HalDevice *device,
+ const char *key);
+
+gboolean hal_device_has_property (HalDevice *device,
+ const char *key);
+gboolean hal_device_has_capability (HalDevice *device,
+ const char *capability);
+gboolean hal_device_has_interface (HalDevice *device,
+ const char *interface);
+
+gboolean hal_device_is_recently_plugged_in (HalDevice *device);
+
+#endif /* HAL_DEVICE_H */
diff --git a/trunk/monitor/hal/hal-marshal.list b/trunk/monitor/hal/hal-marshal.list
new file mode 100644
index 00000000..52c82338
--- /dev/null
+++ b/trunk/monitor/hal/hal-marshal.list
@@ -0,0 +1,3 @@
+VOID:OBJECT,STRING
+VOID:OBJECT,STRING,STRING
+VOID:STRING,STRING
diff --git a/trunk/monitor/hal/hal-pool.c b/trunk/monitor/hal/hal-pool.c
new file mode 100644
index 00000000..770effd9
--- /dev/null
+++ b/trunk/monitor/hal/hal-pool.c
@@ -0,0 +1,458 @@
+/* hal-pool.c
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <gdbusutils.h>
+
+#include "hal-pool.h"
+#include "hal-marshal.h"
+
+enum {
+ DEVICE_ADDED,
+ DEVICE_REMOVED,
+ DEVICE_PROPERTY_CHANGED,
+ DEVICE_CONDITION,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _HalPoolPrivate
+{
+ char **cap_only;
+
+ DBusConnection *dbus_connection;
+ LibHalContext *hal_ctx;
+ GHashTable *devices;
+};
+
+G_DEFINE_TYPE (HalPool, hal_pool, G_TYPE_OBJECT)
+
+static void
+hal_pool_finalize (HalPool *pool)
+{
+ g_strfreev (pool->priv->cap_only);
+
+ dbus_bus_remove_match (pool->priv->dbus_connection,
+ "type='signal',"
+ "interface='org.freedesktop.Hal.Device',"
+ "sender='org.freedesktop.Hal'", NULL);
+ libhal_ctx_shutdown (pool->priv->hal_ctx, NULL);
+ dbus_connection_close (pool->priv->dbus_connection);
+ dbus_connection_unref (pool->priv->dbus_connection);
+
+ if (G_OBJECT_CLASS (hal_pool_parent_class)->finalize)
+ (* G_OBJECT_CLASS (hal_pool_parent_class)->finalize) (G_OBJECT (pool));
+}
+
+static void
+hal_pool_class_init (HalPoolClass *klass)
+{
+ GObjectClass *obj_class = (GObjectClass *) klass;
+
+ obj_class->finalize = (GObjectFinalizeFunc) hal_pool_finalize;
+
+ g_type_class_ref (HAL_TYPE_DEVICE);
+
+ signals[DEVICE_ADDED] =
+ g_signal_new ("device_added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ HAL_TYPE_DEVICE);
+
+ signals[DEVICE_REMOVED] =
+ g_signal_new ("device_removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ HAL_TYPE_DEVICE);
+
+ signals[DEVICE_PROPERTY_CHANGED] =
+ g_signal_new ("device_property_changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_property_changed),
+ NULL, NULL,
+ hal_marshal_VOID__OBJECT_STRING,
+ G_TYPE_NONE, 2,
+ HAL_TYPE_DEVICE,
+ G_TYPE_STRING);
+
+ signals[DEVICE_CONDITION] =
+ g_signal_new ("device_condition",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalPoolClass, device_condition),
+ NULL, NULL,
+ hal_marshal_VOID__OBJECT_STRING_STRING,
+ G_TYPE_NONE, 3,
+ HAL_TYPE_DEVICE,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+}
+
+static void
+hal_pool_init (HalPool *pool)
+{
+ pool->priv = g_new0 (HalPoolPrivate, 1);
+ pool->priv->hal_ctx = NULL;
+}
+
+static gboolean
+has_cap_only (HalPool *pool, HalDevice *device)
+{
+ const char *subsys;
+ unsigned int n;
+
+ for (n = 0; pool->priv->cap_only != NULL && pool->priv->cap_only[n] != NULL; n++)
+ {
+ if (hal_device_has_capability (device, pool->priv->cap_only[n]))
+ return TRUE;
+
+ subsys = hal_device_get_property_string (device, "info.subsystem");
+
+ if (subsys != NULL && strcmp (subsys, pool->priv->cap_only[n]) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+hal_pool_add_device_by_udi (HalPool *pool,
+ const char *udi,
+ gboolean emit_signal)
+{
+ HalDevice *device;
+
+ device = hal_device_new_from_udi (pool->priv->hal_ctx, udi);
+ if (device != NULL)
+ {
+ if (!has_cap_only (pool, device))
+ g_object_unref (device);
+ else
+ {
+ g_hash_table_insert (pool->priv->devices, g_strdup (udi), device);
+ if (emit_signal)
+ g_signal_emit (pool, signals[DEVICE_ADDED], 0, device);
+ }
+ }
+}
+
+#ifdef HAVE_HAL_FAST_INIT
+static void
+hal_pool_add_device_by_udi_and_properties (HalPool *pool,
+ char *udi,
+ LibHalPropertySet *properties,
+ gboolean emit_signal)
+{
+ HalDevice *device;
+
+ device = hal_device_new_from_udi_and_properties (pool->priv->hal_ctx, udi, properties);
+ if (device != NULL)
+ {
+ if (!has_cap_only (pool, device))
+ g_object_unref (device);
+ else
+ {
+ g_hash_table_insert (pool->priv->devices, g_strdup (udi), device);
+ if (emit_signal)
+ g_signal_emit (pool, signals[DEVICE_ADDED], 0, device);
+ }
+ }
+}
+#endif
+
+static void
+_hal_device_added (LibHalContext *hal_ctx, const char *udi)
+{
+ HalPool *pool;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx));
+ hal_pool_add_device_by_udi (pool, udi, TRUE);
+}
+
+static void
+_hal_device_removed (LibHalContext *hal_ctx, const char *udi)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (hal_ctx));
+ if ((device = hal_pool_get_device_by_udi (pool, udi)) != NULL)
+ {
+ g_object_ref (device);
+ g_hash_table_remove (pool->priv->devices, udi);
+ g_signal_emit (pool, signals[DEVICE_REMOVED], 0, device);
+ g_object_unref (device);
+ }
+}
+
+void
+_hal_device_hal_property_changed (HalDevice *device, const char *key);
+
+void
+_hal_device_hal_condition (HalDevice *device, const char *name, const char *detail);
+
+static void
+_hal_property_modified (LibHalContext *ctx,
+ const char *udi,
+ const char *key,
+ dbus_bool_t is_removed,
+ dbus_bool_t is_added)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (ctx));
+
+ device = hal_pool_get_device_by_udi (pool, udi);
+ if (device != NULL)
+ {
+ _hal_device_hal_property_changed (device, key);
+ g_signal_emit (pool, signals[DEVICE_PROPERTY_CHANGED], 0, device, key);
+ }
+}
+
+static void
+_hal_condition (LibHalContext *ctx,
+ const char *udi,
+ const char *condition_name,
+ const char *condition_detail)
+{
+ HalPool *pool;
+ HalDevice *device;
+
+ pool = HAL_POOL (libhal_ctx_get_user_data (ctx));
+
+ device = hal_pool_get_device_by_udi (pool, udi);
+ if (device != NULL)
+ {
+ _hal_device_hal_condition (device, condition_name, condition_detail);
+ g_signal_emit (pool, signals[DEVICE_CONDITION], 0, device, condition_name, condition_detail);
+ }
+}
+
+LibHalContext *
+hal_pool_get_hal_ctx (HalPool *pool)
+{
+ return pool->priv->hal_ctx;
+}
+
+DBusConnection *
+hal_pool_get_dbus_connection (HalPool *pool)
+{
+ return pool->priv->dbus_connection;
+}
+
+HalPool *
+hal_pool_new (char **cap_only)
+{
+ int i;
+ char **devices;
+ int num_devices;
+ HalPool *pool;
+ LibHalContext *hal_ctx;
+ DBusError error;
+ DBusConnection *dbus_connection;
+#ifdef HAVE_HAL_FAST_INIT
+ LibHalPropertySet **properties;
+#endif
+
+ pool = NULL;
+
+ dbus_error_init (&error);
+ /* see discussion on gtk-devel-list (Subject: Re: gvfs hal volume monitoring backend) on
+ * why this is private
+ */
+ dbus_connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+ if (dbus_error_is_set (&error))
+ {
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
+
+ hal_ctx = libhal_ctx_new ();
+ if (hal_ctx == NULL)
+ {
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ goto out;
+ }
+
+ _g_dbus_connection_integrate_with_main (dbus_connection);
+ libhal_ctx_set_dbus_connection (hal_ctx, dbus_connection);
+
+ if (!libhal_ctx_init (hal_ctx, &error))
+ {
+ dbus_connection_close (dbus_connection);
+ dbus_connection_unref (dbus_connection);
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ pool = HAL_POOL (g_object_new (HAL_TYPE_POOL, NULL));
+ pool->priv->dbus_connection = dbus_connection;
+ pool->priv->hal_ctx = hal_ctx;
+ pool->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ pool->priv->cap_only = g_strdupv (cap_only);
+
+ /* Gah, unfortunately we have to watch all devices as HAL's PropertyModified signal
+ * doesn't include the capabilities...
+ */
+ dbus_bus_add_match (dbus_connection,
+ "type='signal',"
+ "interface='org.freedesktop.Hal.Device',"
+ "sender='org.freedesktop.Hal'", NULL);
+ libhal_ctx_set_device_added (hal_ctx, _hal_device_added);
+ libhal_ctx_set_device_removed (hal_ctx, _hal_device_removed);
+ libhal_ctx_set_device_property_modified (hal_ctx, _hal_property_modified);
+ libhal_ctx_set_device_condition (hal_ctx, _hal_condition);
+ libhal_ctx_set_user_data (hal_ctx, pool);
+
+#ifdef HAVE_HAL_FAST_INIT
+ /* First try new O(1) algorithm to get all devices and properties in a single call..
+ *
+ * This method is only available in post hal 0.5.10.
+ */
+ if (libhal_get_all_devices_with_properties (pool->priv->hal_ctx,
+ &num_devices,
+ &devices,
+ &properties,
+ NULL))
+ {
+ for (i = 0; i < num_devices; i++)
+ hal_pool_add_device_by_udi_and_properties (pool, devices[i], properties[i], FALSE);
+ libhal_free_string_array (devices);
+ free (properties); /* hal_pool_add_device_by_udi_and_properties steals the given properties */
+ goto out;
+ }
+#endif
+
+ /* fallback to using O(n) algorithm; will work on any hal 0.5.x release */
+ devices = libhal_get_all_devices (pool->priv->hal_ctx, &num_devices, NULL);
+ if (devices != NULL)
+ {
+ for (i = 0; i < num_devices; i++)
+ {
+ char *device_udi;
+ device_udi = devices[i];
+ hal_pool_add_device_by_udi (pool, device_udi, FALSE);
+ }
+ libhal_free_string_array (devices);
+ goto out;
+ }
+
+ /* FAIL! */
+
+ g_object_unref (pool);
+ return NULL;
+
+ out:
+ return pool;
+}
+
+HalDevice *
+hal_pool_get_device_by_udi (HalPool *pool, const char *udi)
+{
+ return g_hash_table_lookup (pool->priv->devices, udi);
+}
+
+HalDevice *
+hal_pool_get_device_by_capability_and_string (HalPool *pool,
+ const char *capability,
+ const char *key,
+ const char *value)
+{
+ GList *i;
+ GList *devices;
+ HalDevice *result;
+
+ result = NULL;
+ devices = NULL;
+
+ if (pool->priv->devices == NULL)
+ goto out;
+
+ devices = g_hash_table_get_values (pool->priv->devices);
+ for (i = devices; i != NULL; i = i->next)
+ {
+ HalDevice *d = i->data;
+ const char *s;
+
+ if (!hal_device_has_capability (d, capability))
+ continue;
+
+ s = hal_device_get_property_string (d, key);
+ if (s == NULL)
+ continue;
+
+ if (strcmp (s, value) == 0)
+ {
+ result = d;
+ goto out;
+ }
+ }
+
+out:
+ if (devices != NULL)
+ g_list_free (devices);
+ return result;
+}
+
+GList *
+hal_pool_find_by_capability (HalPool *pool, const char *capability)
+{
+ GList *i;
+ GList *j;
+ GList *devices;
+
+ devices = NULL;
+
+ if (pool->priv->devices == NULL)
+ goto out;
+
+ devices = g_hash_table_get_values (pool->priv->devices);
+ for (i = devices; i != NULL; i = j)
+ {
+ HalDevice *d = i->data;
+
+ j = i->next;
+
+ if (!hal_device_has_capability (d, capability))
+ devices = g_list_delete_link (devices, i);
+ }
+
+ out:
+ return devices;
+}
diff --git a/trunk/monitor/hal/hal-pool.h b/trunk/monitor/hal/hal-pool.h
new file mode 100644
index 00000000..04c8687d
--- /dev/null
+++ b/trunk/monitor/hal/hal-pool.h
@@ -0,0 +1,74 @@
+/* hal-pool.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined(HAL_POOL_H)
+#define HAL_POOL_H
+
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include "hal-device.h"
+
+#define HAL_TYPE_POOL (hal_pool_get_type ())
+#define HAL_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HAL_TYPE_POOL, HalPool))
+#define HAL_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HAL_POOL, HalPoolClass))
+#define HAL_IS_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HAL_TYPE_POOL))
+#define HAL_IS_POOL_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), HAL_TYPE_POOL))
+#define HAL_POOL_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), HAL_TYPE_POOL, HalPoolClass))
+
+
+typedef struct _HalPool HalPool;
+typedef struct _HalPoolClass HalPoolClass;
+
+struct _HalPoolPrivate;
+typedef struct _HalPoolPrivate HalPoolPrivate;
+
+struct _HalPool
+{
+ GObject parent;
+
+ /* private */
+ HalPoolPrivate *priv;
+};
+
+struct _HalPoolClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*device_added) (HalPool *pool, HalDevice *device);
+ void (*device_removed) (HalPool *pool, HalDevice *device);
+ void (*device_property_changed) (HalPool *pool, HalDevice *device, const char *key);
+ void (*device_condition) (HalPool *pool, HalDevice *device, const char *name, const char *detail);
+};
+
+GType hal_pool_get_type (void);
+HalPool * hal_pool_new (char **cap_only);
+LibHalContext * hal_pool_get_hal_ctx (HalPool *pool);
+DBusConnection * hal_pool_get_dbus_connection (HalPool *pool);
+HalDevice * hal_pool_get_device_by_udi (HalPool *pool,
+ const char *udi);
+HalDevice * hal_pool_get_device_by_capability_and_string (HalPool *pool,
+ const char *capability,
+ const char *key,
+ const char *value);
+GList * hal_pool_find_by_capability (HalPool *pool,
+ const char *capability);
+
+#endif /* HAL_POOL_H */
diff --git a/trunk/monitor/hal/hal-utils.c b/trunk/monitor/hal/hal-utils.c
new file mode 100644
index 00000000..6bf0cd8c
--- /dev/null
+++ b/trunk/monitor/hal/hal-utils.c
@@ -0,0 +1,171 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ * Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "string.h"
+
+#include "hal-utils.h"
+
+static const struct {
+ const char *disc_type;
+ const char *icon_name;
+ char *ui_name;
+ char *ui_name_blank;
+} disc_data[] = {
+ {"cd_rom", "media-optical-cd-rom", N_("CD-ROM Disc"), N_("Blank CD-ROM Disc")},
+ {"cd_r", "media-optical-cd-r", N_("CD-R Disc"), N_("Blank CD-R Disc")},
+ {"cd_rw", "media-optical-cd-rw", N_("CD-RW Disc"), N_("Blank CD-RW Disc")},
+ {"dvd_rom", "media-optical-dvd-rom", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")},
+ {"dvd_ram", "media-optical-dvd-ram", N_("DVD-RAM Disc"), N_("Blank DVD-RAM Disc")},
+ {"dvd_r", "media-optical-dvd-r", N_("DVD-ROM Disc"), N_("Blank DVD-ROM Disc")},
+ {"dvd_rw", "media-optical-dvd-rw", N_("DVD-RW Disc"), N_("Blank DVD-RW Disc")},
+ {"dvd_plus_r", "media-optical-dvd-r-plus", N_("DVD+R Disc"), N_("Blank DVD+R Disc")},
+ {"dvd_plus_rw", "media-optical-dvd-rw-plus", N_("DVD+RW Disc"), N_("Blank DVD+RW Disc")},
+ {"dvd_plus_r_dl", "media-optical-dvd-dl-r-plus", N_("DVD+R DL Disc"), N_("Blank DVD+R DL Disc")},
+ {"bd_rom", "media-optical-bd-rom", N_("Blu-Ray Disc"), N_("Blank Blu-Ray Disc")},
+ {"bd_r", "media-optical-bd-r", N_("Blu-Ray R Disc"), N_("Blank Blu-Ray R Disc")},
+ {"bd_re", "media-optical-bd-re", N_("Blu-Ray RW Disc"), N_("Blank Blu-Ray RW Disc")},
+ {"hddvd_rom", "media-optical-hddvd-rom", N_("HD DVD Disc"), N_("Blank HD DVD Disc")},
+ {"hddvd_r", "media-optical-hddvd-r", N_("HD DVD-R Disc"), N_("Blank HD DVD-R Disc")},
+ {"hddvd_rw", "media-optical-hddvd-rw", N_("HD DVD-RW Disc"), N_("Blank HD DVD-RW Disc")},
+ {"mo", "media-optical-mo", N_("MO Disc"), N_("Blank MO Disc")},
+ {NULL, "media-optical", N_("Disc"), N_("Blank Disc")}
+};
+
+const char *
+get_disc_icon (const char *disc_type)
+{
+ int n;
+
+ for (n = 0; disc_data[n].disc_type != NULL; n++)
+ {
+ if (strcmp (disc_data[n].disc_type, disc_type) == 0)
+ break;
+ }
+
+ return disc_data[n].icon_name;
+}
+
+const char *
+get_disc_name (const char *disc_type, gboolean is_blank)
+{
+ int n;
+
+ for (n = 0; disc_data[n].disc_type != NULL; n++)
+ {
+ if (strcmp (disc_data[n].disc_type, disc_type) == 0)
+ break;
+ }
+
+ if (is_blank)
+ return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name_blank);
+ else
+ return dgettext (GETTEXT_PACKAGE, disc_data[n].ui_name);
+}
+
+/*
+ * Creates a GThemedIcon from icon_name and creates default
+ * fallbacks from fallbacks. Is smart in the case that icon_name
+ * and fallbacks are identically.
+ * Note: See the GThemedIcon documentation for more information
+ * on default fallbacks
+ */
+GIcon *
+get_themed_icon_with_fallbacks (const char *icon_name,
+ const char *fallbacks)
+{
+ int i = 0, dashes = 0;
+ const char *p;
+ char *dashp;
+ char *last;
+ char **names;
+ GIcon *icon;
+
+ if (G_UNLIKELY (icon_name == NULL))
+ return NULL;
+
+ if (fallbacks == NULL)
+ return g_themed_icon_new (icon_name);
+
+ p = fallbacks;
+ while (*p)
+ {
+ if (*p == '-')
+ dashes++;
+ p++;
+ }
+
+ if (strcmp (icon_name, fallbacks))
+ {
+ names = g_new (char *, dashes + 3);
+ names[i++] = g_strdup (icon_name);
+ }
+ else
+ names = g_new (char *, dashes + 2);
+
+ names[i++] = last = g_strdup (fallbacks);
+
+ while ((dashp = strrchr (last, '-')) != NULL)
+ names[i++] = last = g_strndup (last, dashp - last);
+
+ names[i++] = NULL;
+ icon = g_themed_icon_new_from_names (names, -1);
+ g_strfreev (names);
+
+ return icon;
+}
+
+char **
+dupv_and_uniqify (char **str_array)
+{
+ int n, m, o;
+ int len;
+ char **result;
+
+ result = g_strdupv (str_array);
+ len = g_strv_length (result);
+
+ for (n = 0; n < len; n++)
+ {
+ char *s = result[n];
+ for (m = n + 1; m < len; m++)
+ {
+ char *p = result[m];
+ if (strcmp (s, p) == 0)
+ {
+ for (o = m + 1; o < len; o++)
+ result[o - 1] = result[o];
+ len--;
+ result[len] = NULL;
+ m--;
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/trunk/monitor/hal/hal-utils.h b/trunk/monitor/hal/hal-utils.h
new file mode 100644
index 00000000..fd737ca2
--- /dev/null
+++ b/trunk/monitor/hal/hal-utils.h
@@ -0,0 +1,42 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ * Chrsitian Kellner <gicmo@gnome.org>
+ */
+
+#ifndef __HAL_UTILS_H__
+#define __HAL_UTILS_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+const char * get_disc_icon (const char *disc_type);
+const char * get_disc_name (const char *disc_type, gboolean is_blank);
+
+GIcon * get_themed_icon_with_fallbacks (const char *icon_name,
+ const char *fallbacks);
+
+char **dupv_and_uniqify (char **str_array);
+
+G_END_DECLS
+
+#endif /* __HAL_UTILS_H__ */
diff --git a/trunk/monitor/hal/hal-volume-monitor-daemon.c b/trunk/monitor/hal/hal-volume-monitor-daemon.c
new file mode 100644
index 00000000..6f83175d
--- /dev/null
+++ b/trunk/monitor/hal/hal-volume-monitor-daemon.c
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include <gvfsproxyvolumemonitordaemon.h>
+
+#include "ghalvolumemonitor.h"
+
+int
+main (int argc, char *argv[])
+{
+ g_vfs_proxy_volume_monitor_daemon_init ();
+ return g_vfs_proxy_volume_monitor_daemon_main (argc,
+ argv,
+ "org.gtk.Private.HalVolumeMonitor",
+ G_TYPE_HAL_VOLUME_MONITOR);
+}
diff --git a/trunk/monitor/hal/hal.monitor b/trunk/monitor/hal/hal.monitor
new file mode 100644
index 00000000..c287f853
--- /dev/null
+++ b/trunk/monitor/hal/hal.monitor
@@ -0,0 +1,5 @@
+[RemoteVolumeMonitor]
+Name=GProxyVolumeMonitorHal
+DBusName=org.gtk.Private.HalVolumeMonitor
+IsNative=true
+NativePriority=2
diff --git a/trunk/monitor/hal/org.gtk.Private.HalVolumeMonitor.service.in b/trunk/monitor/hal/org.gtk.Private.HalVolumeMonitor.service.in
new file mode 100644
index 00000000..c785241d
--- /dev/null
+++ b/trunk/monitor/hal/org.gtk.Private.HalVolumeMonitor.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.Private.HalVolumeMonitor
+Exec=@libexecdir@/gvfs-hal-volume-monitor
diff --git a/trunk/monitor/proxy/Makefile.am b/trunk/monitor/proxy/Makefile.am
new file mode 100644
index 00000000..e85ea271
--- /dev/null
+++ b/trunk/monitor/proxy/Makefile.am
@@ -0,0 +1,68 @@
+
+NULL =
+
+remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors
+
+module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
+
+giomodules_LTLIBRARIES = libgioremote-volume-monitor.la
+
+libgioremote_volume_monitor_la_SOURCES = \
+ remote-volume-monitor-module.c \
+ gproxydrive.c gproxydrive.h \
+ gproxyvolume.c gproxyvolume.h \
+ gproxymount.c gproxymount.h \
+ gproxyshadowmount.c gproxyshadowmount.h \
+ gproxyvolumemonitor.c gproxyvolumemonitor.h \
+ $(NULL)
+
+libgioremote_volume_monitor_la_CFLAGS = \
+ -DG_LOG_DOMAIN=\"GVFS-RemoteVolumeMonitor\" \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ -DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+ -DREMOTE_VOLUME_MONITORS_DIR=\"$(remote_volume_monitorsdir)\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+libgioremote_volume_monitor_la_LDFLAGS = \
+ $(module_flags) \
+ $(NULL)
+
+libgioremote_volume_monitor_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(NULL)
+
+############################################################################
+
+noinst_LTLIBRARIES = libgvfsproxyvolumemonitordaemon-noin.la
+
+libgvfsproxyvolumemonitordaemon_noin_la_SOURCES = \
+ gvfsproxyvolumemonitordaemon.c \
+ gvfsproxyvolumemonitordaemon.h
+
+libgvfsproxyvolumemonitordaemon_noin_la_CFLAGS = \
+ -I$(top_srcdir)/common \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GDU_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS-RemoteVolumeMonitorDaemon\" \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED \
+ $(NULL)
+
+libgvfsproxyvolumemonitordaemon_noin_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_LIBS) \
+ $(top_builddir)/common/libgvfscommon.la \
+ $(NULL)
+
+clean-local:
+ rm -f *~ *.loT
+
+install-data-local:
+ mkdir -p $(DESTDIR)$(remote_volume_monitorsdir)
diff --git a/trunk/monitor/proxy/gproxydrive.c b/trunk/monitor/proxy/gproxydrive.c
new file mode 100644
index 00000000..79459935
--- /dev/null
+++ b/trunk/monitor/proxy/gproxydrive.c
@@ -0,0 +1,731 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxydrive.h"
+#include "gproxyvolume.h"
+
+/* Protects all fields of GProxyDrive that can change */
+G_LOCK_DEFINE_STATIC(proxy_drive);
+
+struct _GProxyDrive {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ char *id;
+ char *name;
+ GIcon *icon;
+ char **volume_ids;
+ gboolean can_eject;
+ gboolean can_poll_for_media;
+ gboolean is_media_check_automatic;
+ gboolean has_media;
+ gboolean is_media_removable;
+
+ GHashTable *identifiers;
+};
+
+static void g_proxy_drive_drive_iface_init (GDriveIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyDrive, g_proxy_drive, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_DRIVE,
+ g_proxy_drive_drive_iface_init))
+
+static void
+g_proxy_drive_finalize (GObject *object)
+{
+ GProxyDrive *drive;
+
+ drive = G_PROXY_DRIVE (object);
+
+ if (drive->volume_monitor != NULL)
+ g_object_unref (drive->volume_monitor);
+ g_free (drive->id);
+ g_free (drive->name);
+ if (drive->icon != NULL)
+ g_object_unref (drive->icon);
+ g_strfreev (drive->volume_ids);
+ if (drive->identifiers != NULL)
+ g_hash_table_unref (drive->identifiers);
+
+ if (G_OBJECT_CLASS (g_proxy_drive_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_drive_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_drive_class_init (GProxyDriveClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_drive_finalize;
+}
+
+static void
+g_proxy_drive_class_finalize (GProxyDriveClass *klass)
+{
+}
+
+static void
+g_proxy_drive_init (GProxyDrive *proxy_drive)
+{
+}
+
+GProxyDrive *
+g_proxy_drive_new (GProxyVolumeMonitor *volume_monitor)
+{
+ GProxyDrive *drive;
+ drive = g_object_new (G_TYPE_PROXY_DRIVE, NULL);
+ drive->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (drive),
+ "g-proxy-drive-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+ return drive;
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * boolean can-eject
+ * boolean can-poll-for-media
+ * boolean has-media
+ * boolean is-media-removable
+ * boolean is-media-check-automatic
+ * array:string volume-ids
+ * dict:string->string identifiers
+ */
+#define DRIVE_STRUCT_TYPE "(sssbbbbasa{ss})"
+
+void
+g_proxy_drive_update (GProxyDrive *drive,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_volume_ids_iter;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ dbus_bool_t can_eject;
+ dbus_bool_t can_poll_for_media;
+ dbus_bool_t has_media;
+ dbus_bool_t is_media_removable;
+ dbus_bool_t is_media_check_automatic;
+ GPtrArray *volume_ids;
+ GHashTable *identifiers;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_eject);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_poll_for_media);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &has_media);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &is_media_removable);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &is_media_check_automatic);
+ dbus_message_iter_next (&iter_struct);
+
+ volume_ids = g_ptr_array_new ();
+ dbus_message_iter_recurse (&iter_struct, &iter_volume_ids_iter);
+ while (dbus_message_iter_get_arg_type (&iter_volume_ids_iter) != DBUS_TYPE_INVALID)
+ {
+ const char *volume_id;
+ dbus_message_iter_get_basic (&iter_volume_ids_iter, &volume_id);
+ dbus_message_iter_next (&iter_volume_ids_iter);
+ g_ptr_array_add (volume_ids, (gpointer) volume_id);
+ }
+ g_ptr_array_add (volume_ids, NULL);
+ dbus_message_iter_next (&iter_struct);
+
+ identifiers = _get_identifiers (&iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ if (drive->id != NULL && strcmp (drive->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of drive");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+
+ /* out with the old */
+ g_free (drive->id);
+ g_free (drive->name);
+ if (drive->icon != NULL)
+ g_object_unref (drive->icon);
+ g_strfreev (drive->volume_ids);
+ if (drive->identifiers != NULL)
+ g_hash_table_unref (drive->identifiers);
+
+ /* in with the new */
+ drive->id = g_strdup (id);
+ drive->name = g_strdup (name);
+ if (*gicon_data == 0)
+ drive->icon = NULL;
+ else
+ drive->icon = g_icon_new_for_string (gicon_data, NULL);
+
+ drive->can_eject = can_eject;
+ drive->can_poll_for_media = can_poll_for_media;
+ drive->has_media = has_media;
+ drive->is_media_removable = is_media_removable;
+ drive->is_media_check_automatic = is_media_check_automatic;
+ drive->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
+ drive->volume_ids = g_strdupv ((char **) volume_ids->pdata);
+
+ out:
+ g_ptr_array_free (volume_ids, TRUE);
+ g_hash_table_unref (identifiers);
+}
+
+static GIcon *
+g_proxy_drive_get_icon (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GIcon *icon;
+
+ G_LOCK (proxy_drive);
+ icon = proxy_drive->icon != NULL ? g_object_ref (proxy_drive->icon) : NULL;
+ G_UNLOCK (proxy_drive);
+
+ return icon;
+}
+
+static char *
+g_proxy_drive_get_name (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ char *name;
+
+ G_LOCK (proxy_drive);
+ name = g_strdup (proxy_drive->name);
+ G_UNLOCK (proxy_drive);
+
+ return name;
+}
+
+static GList *
+g_proxy_drive_get_volumes (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GList *l;
+
+ l = NULL;
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->volume_monitor != NULL && proxy_drive->volume_ids != NULL)
+ {
+ int n;
+
+ for (n = 0; proxy_drive->volume_ids[n] != NULL; n++)
+ {
+ GProxyVolume *volume;
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_drive->volume_monitor, proxy_drive->volume_ids[n]);
+ if (volume != NULL)
+ l = g_list_append (l, volume);
+ }
+ }
+ G_UNLOCK (proxy_drive);
+
+ return l;
+}
+
+static gboolean
+g_proxy_drive_has_volumes (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = (proxy_drive->volume_ids != NULL && g_strv_length (proxy_drive->volume_ids) > 0);
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_is_media_removable (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->is_media_removable;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_has_media (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->has_media;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_is_media_check_automatic (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->is_media_check_automatic;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_can_eject (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->can_eject;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static gboolean
+g_proxy_drive_can_poll_for_media (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ gboolean res;
+
+ G_LOCK (proxy_drive);
+ res = proxy_drive->can_poll_for_media;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static char *
+g_proxy_drive_get_identifier (GDrive *drive,
+ const char *kind)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ char *res;
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->identifiers != NULL)
+ res = g_strdup (g_hash_table_lookup (proxy_drive->identifiers, kind));
+ else
+ res = NULL;
+ G_UNLOCK (proxy_drive);
+
+ return res;
+}
+
+static void
+add_identifier_key (const char *key, const char *value, GPtrArray *res)
+{
+ g_ptr_array_add (res, g_strdup (key));
+}
+
+static char **
+g_proxy_drive_enumerate_identifiers (GDrive *drive)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ GPtrArray *res;
+
+ res = g_ptr_array_new ();
+
+ G_LOCK (proxy_drive);
+ if (proxy_drive->identifiers != NULL)
+ g_hash_table_foreach (proxy_drive->identifiers, (GHFunc) add_identifier_key, res);
+ G_UNLOCK (proxy_drive);
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **) g_ptr_array_free (res, FALSE);
+}
+
+const char *
+g_proxy_drive_get_id (GProxyDrive *drive)
+{
+ return drive->id;
+}
+
+typedef struct {
+ GProxyDrive *drive;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+ gchar *cancellation_id;
+ GCancellable *cancellable;
+ gulong cancelled_handler_id;
+} DBusOp;
+
+static void
+cancel_operation_reply_cb (DBusMessage *reply,
+ GError *error,
+ gpointer user_data)
+{
+ if (error != NULL)
+ {
+ g_warning ("Error from CancelOperation(): %s", error->message);
+ }
+}
+
+static void
+operation_cancelled (GCancellable *cancellable,
+ gpointer user_data)
+{
+ DBusOp *data = user_data;
+ GSimpleAsyncResult *simple;
+ DBusConnection *connection;
+ DBusMessage *message;
+ const char *name;
+
+ G_LOCK (proxy_drive);
+
+ simple = g_simple_async_result_new_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ /* Now tell the remote volume monitor that the op has been cancelled */
+ connection = g_proxy_volume_monitor_get_dbus_connection (data->drive->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (data->drive->volume_monitor);
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "CancelOperation");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_INVALID);
+
+ G_UNLOCK (proxy_drive);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) cancel_operation_reply_cb,
+ NULL);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+}
+
+static void
+eject_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ if (data->cancelled_handler_id > 0)
+ g_signal_handler_disconnect (data->cancellable, data->cancelled_handler_id);
+
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ {
+ GSimpleAsyncResult *simple;
+
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+
+ g_object_unref (data->drive);
+ g_free (data->cancellation_id);
+ if (data->cancellable != NULL)
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+static void
+g_proxy_drive_eject (GDrive *drive,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+ dbus_uint32_t _flags = flags;
+
+ G_LOCK (proxy_drive);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (drive),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ G_UNLOCK (proxy_drive);
+ goto out;
+ }
+
+ data = g_new0 (DBusOp, 1);
+ data->drive = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (cancellable != NULL)
+ {
+ data->cancellation_id = g_strdup_printf ("%p", cancellable);
+ data->cancellable = g_object_ref (cancellable);
+ data->cancelled_handler_id = g_signal_connect (data->cancellable,
+ "cancelled",
+ G_CALLBACK (operation_cancelled),
+ data);
+ }
+ else
+ {
+ data->cancellation_id = g_strdup ("");
+ }
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_drive->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_drive->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "DriveEject");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_drive->id),
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_drive);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) eject_cb,
+ data);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+ out:
+ ;
+}
+
+static gboolean
+g_proxy_drive_eject_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+poll_for_media_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ {
+ GSimpleAsyncResult *simple;
+
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+
+ g_object_unref (data->drive);
+ g_free (data->cancellation_id);
+ if (data->cancelled_handler_id > 0)
+ g_signal_handler_disconnect (data->cancellable, data->cancelled_handler_id);
+ if (data->cancellable != NULL)
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+static void
+g_proxy_drive_poll_for_media (GDrive *drive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyDrive *proxy_drive = G_PROXY_DRIVE (drive);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+
+ G_LOCK (proxy_drive);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (drive),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ G_UNLOCK (proxy_drive);
+ goto out;
+ }
+
+ data = g_new0 (DBusOp, 1);
+ data->drive = g_object_ref (drive);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (cancellable != NULL)
+ {
+ data->cancellation_id = g_strdup_printf ("%p", cancellable);
+ data->cancellable = g_object_ref (cancellable);
+ data->cancelled_handler_id = g_signal_connect (data->cancellable,
+ "cancelled",
+ G_CALLBACK (operation_cancelled),
+ data);
+ }
+ else
+ {
+ data->cancellation_id = g_strdup ("");
+ }
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_drive->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_drive->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "DrivePollForMedia");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_drive->id),
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_drive);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) poll_for_media_cb,
+ data);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+ out:
+ ;
+}
+
+static gboolean
+g_proxy_drive_poll_for_media_finish (GDrive *drive,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+
+static void
+g_proxy_drive_drive_iface_init (GDriveIface *iface)
+{
+ iface->get_name = g_proxy_drive_get_name;
+ iface->get_icon = g_proxy_drive_get_icon;
+ iface->has_volumes = g_proxy_drive_has_volumes;
+ iface->get_volumes = g_proxy_drive_get_volumes;
+ iface->is_media_removable = g_proxy_drive_is_media_removable;
+ iface->has_media = g_proxy_drive_has_media;
+ iface->is_media_check_automatic = g_proxy_drive_is_media_check_automatic;
+ iface->can_eject = g_proxy_drive_can_eject;
+ iface->can_poll_for_media = g_proxy_drive_can_poll_for_media;
+ iface->eject = g_proxy_drive_eject;
+ iface->eject_finish = g_proxy_drive_eject_finish;
+ iface->poll_for_media = g_proxy_drive_poll_for_media;
+ iface->poll_for_media_finish = g_proxy_drive_poll_for_media_finish;
+ iface->get_identifier = g_proxy_drive_get_identifier;
+ iface->enumerate_identifiers = g_proxy_drive_enumerate_identifiers;
+}
+
+void
+g_proxy_drive_register (GIOModule *module)
+{
+ g_proxy_drive_register_type (G_TYPE_MODULE (module));
+}
diff --git a/trunk/monitor/proxy/gproxydrive.h b/trunk/monitor/proxy/gproxydrive.h
new file mode 100644
index 00000000..7494286c
--- /dev/null
+++ b/trunk/monitor/proxy/gproxydrive.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_DRIVE_H__
+#define __G_PROXY_DRIVE_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_DRIVE (g_proxy_drive_get_type ())
+#define G_PROXY_DRIVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_DRIVE, GProxyDrive))
+#define G_PROXY_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_DRIVE, GProxyDriveClass))
+#define G_IS_PROXY_DRIVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_DRIVE))
+#define G_IS_PROXY_DRIVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_DRIVE))
+
+typedef struct _GProxyDriveClass GProxyDriveClass;
+
+struct _GProxyDriveClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_drive_get_type (void) G_GNUC_CONST;
+void g_proxy_drive_register (GIOModule *module);
+GProxyDrive *g_proxy_drive_new (GProxyVolumeMonitor *volume_monitor);
+void g_proxy_drive_update (GProxyDrive *drive,
+ DBusMessageIter *iter);
+const char *g_proxy_drive_get_id (GProxyDrive *drive);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_DRIVE_H__ */
diff --git a/trunk/monitor/proxy/gproxymount.c b/trunk/monitor/proxy/gproxymount.c
new file mode 100644
index 00000000..18259f53
--- /dev/null
+++ b/trunk/monitor/proxy/gproxymount.c
@@ -0,0 +1,665 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxymount.h"
+#include "gproxyvolume.h"
+
+/* Protects all fields of GProxyMount that can change */
+G_LOCK_DEFINE_STATIC(proxy_mount);
+
+struct _GProxyMount {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ char *id;
+ char *name;
+ char *uuid;
+ char *volume_id;
+ gboolean can_unmount;
+ char **x_content_types;
+ GFile *root;
+ GIcon *icon;
+};
+
+static void g_proxy_mount_mount_iface_init (GMountIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyMount, g_proxy_mount, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_MOUNT,
+ g_proxy_mount_mount_iface_init))
+
+static void
+g_proxy_mount_finalize (GObject *object)
+{
+ GProxyMount *mount;
+
+ mount = G_PROXY_MOUNT (object);
+
+ g_free (mount->id);
+ g_free (mount->name);
+ g_free (mount->uuid);
+ g_free (mount->volume_id);
+ g_strfreev (mount->x_content_types);
+ if (mount->icon != NULL)
+ g_object_unref (mount->icon);
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ if (mount->volume_monitor != NULL)
+ g_object_unref (mount->volume_monitor);
+
+ if (G_OBJECT_CLASS (g_proxy_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_mount_class_init (GProxyMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_mount_finalize;
+}
+
+static void
+g_proxy_mount_class_finalize (GProxyMountClass *klass)
+{
+}
+
+static void
+g_proxy_mount_init (GProxyMount *proxy_mount)
+{
+}
+
+GProxyMount *
+g_proxy_mount_new (GProxyVolumeMonitor *volume_monitor)
+{
+ GProxyMount *mount;
+ mount = g_object_new (G_TYPE_PROXY_MOUNT, NULL);
+ mount->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (mount),
+ "g-proxy-mount-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+ return mount;
+}
+
+gboolean
+g_proxy_mount_has_mount_path (GProxyMount *mount, const char *mount_path)
+{
+ char *path;
+ gboolean result;
+ result = FALSE;
+ path = g_file_get_path (mount->root);
+ if (path != NULL)
+ {
+ if (strcmp (path, mount_path) == 0)
+ result = TRUE;
+ g_free (path);
+ }
+ return result;
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string root_uri
+ * boolean can-unmount
+ * string volume-id
+ * array:string x-content-types
+ */
+
+void
+g_proxy_mount_update (GProxyMount *mount,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_x_content_types;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ const char *uuid;
+ const char *root_uri;
+ dbus_bool_t can_unmount;
+ const char *volume_id;
+ GPtrArray *x_content_types;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &uuid);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &root_uri);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_unmount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &volume_id);
+ dbus_message_iter_next (&iter_struct);
+
+ x_content_types = g_ptr_array_new ();
+ dbus_message_iter_recurse (&iter_struct, &iter_x_content_types);
+ while (dbus_message_iter_get_arg_type (&iter_x_content_types) != DBUS_TYPE_INVALID)
+ {
+ const char *x_content_type;
+ dbus_message_iter_get_basic (&iter_x_content_types, &x_content_type);
+ dbus_message_iter_next (&iter_x_content_types);
+ g_ptr_array_add (x_content_types, (gpointer) x_content_type);
+ }
+ g_ptr_array_add (x_content_types, NULL);
+ dbus_message_iter_next (&iter_struct);
+
+ if (mount->id != NULL && strcmp (mount->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of mount");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+ if (strlen (uuid) == 0)
+ uuid = NULL;
+
+ /* out with the old */
+ g_free (mount->id);
+ g_free (mount->name);
+ g_free (mount->uuid);
+ g_free (mount->volume_id);
+ if (mount->icon != NULL)
+ g_object_unref (mount->icon);
+ g_strfreev (mount->x_content_types);
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ /* in with the new */
+ mount->id = g_strdup (id);
+ mount->name = g_strdup (name);
+ if (*gicon_data == 0)
+ mount->icon = NULL;
+ else
+ mount->icon = g_icon_new_for_string (gicon_data, NULL);
+ mount->uuid = g_strdup (uuid);
+ mount->root = g_file_new_for_uri (root_uri);
+ mount->can_unmount = can_unmount;
+ mount->volume_id = g_strdup (volume_id);
+ mount->x_content_types = g_strdupv ((char **) x_content_types->pdata);
+
+ out:
+ g_ptr_array_free (x_content_types, TRUE);
+}
+
+const char *
+g_proxy_mount_get_id (GProxyMount *mount)
+{
+ return mount->id;
+}
+
+static GFile *
+g_proxy_mount_get_root (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GFile *root;
+
+ G_LOCK (proxy_mount);
+ root = proxy_mount->root != NULL ? g_object_ref (proxy_mount->root) : NULL;
+ G_UNLOCK (proxy_mount);
+ return root;
+}
+
+static GIcon *
+g_proxy_mount_get_icon (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GIcon *icon;
+
+ G_LOCK (proxy_mount);
+ icon = proxy_mount->icon != NULL ? g_object_ref (proxy_mount->icon) : NULL;
+ G_UNLOCK (proxy_mount);
+ return icon;
+}
+
+static char *
+g_proxy_mount_get_uuid (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ char *uuid;
+
+ G_LOCK (proxy_mount);
+ uuid = g_strdup (proxy_mount->uuid);
+ G_UNLOCK (proxy_mount);
+ return uuid;
+}
+
+static char *
+g_proxy_mount_get_name (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ char *name;
+
+ G_LOCK (proxy_mount);
+ name = g_strdup (proxy_mount->name);
+ G_UNLOCK (proxy_mount);
+
+ return name;
+}
+
+static GDrive *
+g_proxy_mount_get_drive (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GProxyVolume *volume;
+ GDrive *drive;
+
+ G_LOCK (proxy_mount);
+ volume = NULL;
+ if (proxy_mount->volume_id != NULL && strlen (proxy_mount->volume_id) > 0)
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_mount->volume_monitor,
+ proxy_mount->volume_id);
+ G_UNLOCK (proxy_mount);
+
+ drive = NULL;
+ if (volume != NULL)
+ {
+ drive = g_volume_get_drive (G_VOLUME (volume));
+ g_object_unref (volume);
+ }
+
+ return drive;
+}
+
+static GVolume *
+g_proxy_mount_get_volume (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ GProxyVolume *volume;
+
+ G_LOCK (proxy_mount);
+ volume = NULL;
+ if (proxy_mount->volume_id != NULL && strlen (proxy_mount->volume_id) > 0)
+ volume = g_proxy_volume_monitor_get_volume_for_id (proxy_mount->volume_monitor,
+ proxy_mount->volume_id);
+ G_UNLOCK (proxy_mount);
+
+ return volume != NULL ? G_VOLUME (volume) : NULL;
+}
+
+static gboolean
+g_proxy_mount_can_unmount (GMount *mount)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_mount);
+ res = proxy_mount->can_unmount;
+ G_UNLOCK (proxy_mount);
+
+ return res;
+}
+
+static gboolean
+g_proxy_mount_can_eject (GMount *mount)
+{
+ GDrive *drive;
+ gboolean can_eject;
+
+ can_eject = FALSE;
+ drive = g_proxy_mount_get_drive (mount);
+ if (drive != NULL)
+ {
+ can_eject = g_drive_can_eject (drive);
+ g_object_unref (drive);
+ }
+
+ return can_eject;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDrive *drive;
+
+ drive = g_proxy_mount_get_drive (mount);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_proxy_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GDrive *drive;
+ gboolean res;
+
+ res = TRUE;
+
+ drive = g_proxy_mount_get_drive (mount);
+
+ if (drive != NULL)
+ {
+ res = g_drive_eject_finish (drive, result, error);
+ g_object_unref (drive);
+ }
+ return res;
+}
+
+typedef struct {
+ GProxyMount *mount;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+ gchar *cancellation_id;
+ GCancellable *cancellable;
+ gulong cancelled_handler_id;
+} DBusOp;
+
+static void
+cancel_operation_reply_cb (DBusMessage *reply,
+ GError *error,
+ gpointer user_data)
+{
+ if (error != NULL)
+ {
+ g_warning ("Error from CancelOperation(): %s", error->message);
+ }
+}
+
+static void
+operation_cancelled (GCancellable *cancellable,
+ gpointer user_data)
+{
+ DBusOp *data = user_data;
+ GSimpleAsyncResult *simple;
+ DBusConnection *connection;
+ DBusMessage *message;
+ const char *name;
+
+ G_LOCK (proxy_mount);
+
+ simple = g_simple_async_result_new_error (G_OBJECT (data->mount),
+ data->callback,
+ data->user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ /* Now tell the remote volume monitor that the op has been cancelled */
+ connection = g_proxy_volume_monitor_get_dbus_connection (data->mount->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (data->mount->volume_monitor);
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "CancelOperation");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_INVALID);
+
+ G_UNLOCK (proxy_mount);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) cancel_operation_reply_cb,
+ NULL);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+}
+
+static void
+unmount_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ if (data->cancelled_handler_id > 0)
+ g_signal_handler_disconnect (data->cancellable, data->cancelled_handler_id);
+
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ {
+ GSimpleAsyncResult *simple;
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->mount),
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (G_OBJECT (data->mount),
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+
+ g_object_unref (data->mount);
+ g_free (data->cancellation_id);
+ if (data->cancellable != NULL)
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+static void
+g_proxy_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ DBusOp *data;
+ dbus_uint32_t _flags = flags;
+
+ G_LOCK (proxy_mount);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (mount),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ G_UNLOCK (proxy_mount);
+ goto out;
+ }
+
+ data = g_new0 (DBusOp, 1);
+ data->mount = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (cancellable != NULL)
+ {
+ data->cancellation_id = g_strdup_printf ("%p", cancellable);
+ data->cancellable = g_object_ref (cancellable);
+ data->cancelled_handler_id = g_signal_connect (data->cancellable,
+ "cancelled",
+ G_CALLBACK (operation_cancelled),
+ data);
+ }
+ else
+ {
+ data->cancellation_id = g_strdup ("");
+ }
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_mount->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_mount->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountUnmount");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_mount->id),
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_mount);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) unmount_cb,
+ data);
+
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+ out:
+ ;
+}
+
+static gboolean
+g_proxy_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+g_proxy_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ /* TODO: handle force_rescan */
+ simple = g_simple_async_result_new (G_OBJECT (mount),
+ callback,
+ user_data,
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static char **
+g_proxy_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ return g_strdupv (proxy_mount->x_content_types);
+}
+
+static char **
+g_proxy_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GProxyMount *proxy_mount = G_PROXY_MOUNT (mount);
+ /* TODO: handle force_rescan */
+ return g_strdupv (proxy_mount->x_content_types);
+}
+
+static void
+g_proxy_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_proxy_mount_get_root;
+ iface->get_name = g_proxy_mount_get_name;
+ iface->get_icon = g_proxy_mount_get_icon;
+ iface->get_uuid = g_proxy_mount_get_uuid;
+ iface->get_drive = g_proxy_mount_get_drive;
+ iface->get_volume = g_proxy_mount_get_volume;
+ iface->can_unmount = g_proxy_mount_can_unmount;
+ iface->can_eject = g_proxy_mount_can_eject;
+ iface->unmount = g_proxy_mount_unmount;
+ iface->unmount_finish = g_proxy_mount_unmount_finish;
+ iface->eject = g_proxy_mount_eject;
+ iface->eject_finish = g_proxy_mount_eject_finish;
+ iface->guess_content_type = g_proxy_mount_guess_content_type;
+ iface->guess_content_type_finish = g_proxy_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_proxy_mount_guess_content_type_sync;
+}
+
+void
+g_proxy_mount_register (GIOModule *module)
+{
+ g_proxy_mount_register_type (G_TYPE_MODULE (module));
+}
diff --git a/trunk/monitor/proxy/gproxymount.h b/trunk/monitor/proxy/gproxymount.h
new file mode 100644
index 00000000..c6356518
--- /dev/null
+++ b/trunk/monitor/proxy/gproxymount.h
@@ -0,0 +1,56 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_MOUNT_H__
+#define __G_PROXY_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_MOUNT (g_proxy_mount_get_type ())
+#define G_PROXY_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_MOUNT, GProxyMount))
+#define G_PROXY_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_MOUNT, GProxyMountClass))
+#define G_IS_PROXY_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_MOUNT))
+#define G_IS_PROXY_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_MOUNT))
+
+typedef struct _GProxyMountClass GProxyMountClass;
+
+struct _GProxyMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_mount_get_type (void) G_GNUC_CONST;
+void g_proxy_mount_register (GIOModule *module);
+GProxyMount *g_proxy_mount_new (GProxyVolumeMonitor *volume_monitor);
+void g_proxy_mount_update (GProxyMount *mount,
+ DBusMessageIter *iter);
+const char *g_proxy_mount_get_id (GProxyMount *mount);
+gboolean g_proxy_mount_has_mount_path (GProxyMount *mount, const char *mount_path);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_MOUNT_H__ */
diff --git a/trunk/monitor/proxy/gproxyshadowmount.c b/trunk/monitor/proxy/gproxyshadowmount.c
new file mode 100644
index 00000000..bcf5f221
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyshadowmount.c
@@ -0,0 +1,465 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
+#include "gproxyvolume.h"
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+/* Protects all fields of GProxyShadowMount that can change */
+G_LOCK_DEFINE_STATIC(proxy_shadow_mount);
+
+struct _GProxyShadowMount {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ GProxyVolume *volume;
+ GMount *real_mount;
+ GFile *root;
+};
+
+static void g_proxy_shadow_mount_mount_iface_init (GMountIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyShadowMount, g_proxy_shadow_mount, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_MOUNT,
+ g_proxy_shadow_mount_mount_iface_init))
+
+static void
+g_proxy_shadow_mount_finalize (GObject *object)
+{
+ GProxyShadowMount *mount;
+
+ mount = G_PROXY_SHADOW_MOUNT (object);
+
+ g_proxy_shadow_mount_remove (mount);
+
+ if (mount->volume_monitor != NULL)
+ g_object_unref (mount->volume_monitor);
+
+ if (mount->volume != NULL)
+ g_object_unref (mount->volume);
+
+ if (mount->root != NULL)
+ g_object_unref (mount->root);
+
+ if (G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_shadow_mount_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_shadow_mount_class_init (GProxyShadowMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_shadow_mount_finalize;
+}
+
+static void
+g_proxy_shadow_mount_class_finalize (GProxyShadowMountClass *klass)
+{
+}
+
+static void
+g_proxy_shadow_mount_init (GProxyShadowMount *proxy_shadow_mount)
+{
+}
+
+void
+g_proxy_shadow_mount_remove (GProxyShadowMount *mount)
+{
+ if (mount->real_mount != NULL)
+ {
+ g_mount_unshadow (mount->real_mount);
+ signal_emit_in_idle (mount->real_mount, "changed", NULL);
+ signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+ g_object_unref (mount->real_mount);
+ mount->real_mount = NULL;
+ }
+}
+
+GProxyShadowMount *
+g_proxy_shadow_mount_new (GProxyVolumeMonitor *volume_monitor,
+ GProxyVolume *volume,
+ GMount *real_mount)
+{
+ GProxyShadowMount *mount;
+ GFile *activation_root;
+
+ mount = NULL;
+
+ activation_root = g_volume_get_activation_root (G_VOLUME (volume));
+ if (activation_root == NULL)
+ {
+ g_warning ("Cannot construct a GProxyShadowMount object for a volume without an activation root");
+ goto out;
+ }
+
+ mount = g_object_new (G_TYPE_PROXY_SHADOW_MOUNT, NULL);
+ mount->volume_monitor = g_object_ref (volume_monitor);
+ mount->volume = g_object_ref (volume);
+ mount->real_mount = g_object_ref (real_mount);
+ mount->root = activation_root;
+
+ g_mount_shadow (mount->real_mount);
+ signal_emit_in_idle (mount->real_mount, "changed", NULL);
+ signal_emit_in_idle (mount->volume_monitor, "mount-changed", mount->real_mount);
+
+ g_object_set_data (G_OBJECT (mount),
+ "g-proxy-shadow-mount-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+
+ out:
+ return mount;
+}
+
+gboolean
+g_proxy_shadow_mount_has_mount_path (GProxyShadowMount *mount, const char *mount_path)
+{
+ char *path;
+ gboolean result;
+ result = FALSE;
+ path = g_file_get_path (mount->root);
+ if (path != NULL)
+ {
+ if (strcmp (path, mount_path) == 0)
+ result = TRUE;
+ g_free (path);
+ }
+ return result;
+}
+
+static GFile *
+g_proxy_shadow_mount_get_root (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GFile *root;
+
+ G_LOCK (proxy_shadow_mount);
+ root = g_object_ref (proxy_shadow_mount->root);
+ G_UNLOCK (proxy_shadow_mount);
+ return root;
+}
+
+static GIcon *
+g_proxy_shadow_mount_get_icon (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GIcon *icon;
+
+ G_LOCK (proxy_shadow_mount);
+ icon = g_volume_get_icon (G_VOLUME (proxy_shadow_mount->volume));
+ G_UNLOCK (proxy_shadow_mount);
+ return icon;
+}
+
+static char *
+g_proxy_shadow_mount_get_uuid (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ char *uuid;
+
+ G_LOCK (proxy_shadow_mount);
+ uuid = g_mount_get_uuid (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+ return uuid;
+}
+
+static char *
+g_proxy_shadow_mount_get_name (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ char *name;
+
+ G_LOCK (proxy_shadow_mount);
+ name = g_volume_get_name (G_VOLUME (proxy_shadow_mount->volume));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return name;
+}
+
+static GDrive *
+g_proxy_shadow_mount_get_drive (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GDrive *drive;
+
+ G_LOCK (proxy_shadow_mount);
+ drive = g_mount_get_drive (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return drive;
+}
+
+static GVolume *
+g_proxy_shadow_mount_get_volume (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ GVolume *volume;
+
+ G_LOCK (proxy_shadow_mount);
+ volume = g_object_ref (proxy_shadow_mount->volume);
+ G_UNLOCK (proxy_shadow_mount);
+
+ return volume;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_unmount (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_shadow_mount);
+ res = g_mount_can_unmount (G_MOUNT (proxy_shadow_mount->real_mount));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return res;
+}
+
+static gboolean
+g_proxy_shadow_mount_can_eject (GMount *mount)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_shadow_mount);
+ res = g_volume_can_eject (G_VOLUME (proxy_shadow_mount->volume));
+ G_UNLOCK (proxy_shadow_mount);
+
+ return res;
+}
+
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_shadow_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ EjectWrapperOp *data;
+
+ G_LOCK (proxy_shadow_mount);
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (mount);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_volume_eject (G_VOLUME (proxy_shadow_mount->volume), flags, cancellable, eject_wrapper_callback, data);
+ G_UNLOCK (proxy_shadow_mount);
+}
+
+static gboolean
+g_proxy_shadow_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ gboolean res;
+
+ G_LOCK (proxy_shadow_mount);
+ res = g_volume_eject_finish (G_VOLUME (proxy_shadow_mount->volume), result, error);
+ G_UNLOCK (proxy_shadow_mount);
+
+ return res;
+}
+
+static void
+g_proxy_shadow_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ g_mount_unmount (proxy_shadow_mount->real_mount,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static gboolean
+g_proxy_shadow_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ return g_mount_unmount_finish (proxy_shadow_mount->real_mount,
+ result,
+ error);
+}
+
+static void
+g_proxy_shadow_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ g_mount_guess_content_type (proxy_shadow_mount->real_mount,
+ force_rescan,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+
+ return g_mount_guess_content_type_finish (proxy_shadow_mount->real_mount,
+ result,
+ error);
+}
+
+static char **
+g_proxy_shadow_mount_guess_content_type_sync (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GProxyShadowMount *proxy_shadow_mount = G_PROXY_SHADOW_MOUNT (mount);
+ return g_mount_guess_content_type_sync (proxy_shadow_mount->real_mount,
+ force_rescan,
+ cancellable,
+ error);
+}
+
+GMount *
+g_proxy_shadow_mount_get_real_mount (GProxyShadowMount *mount)
+{
+ return g_object_ref (mount->real_mount);
+}
+
+GFile *
+g_proxy_shadow_mount_get_activation_root (GProxyShadowMount *mount)
+{
+ return g_object_ref (mount->root);
+}
+
+static void
+g_proxy_shadow_mount_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_proxy_shadow_mount_get_root;
+ iface->get_name = g_proxy_shadow_mount_get_name;
+ iface->get_icon = g_proxy_shadow_mount_get_icon;
+ iface->get_uuid = g_proxy_shadow_mount_get_uuid;
+ iface->get_drive = g_proxy_shadow_mount_get_drive;
+ iface->get_volume = g_proxy_shadow_mount_get_volume;
+ iface->can_unmount = g_proxy_shadow_mount_can_unmount;
+ iface->can_eject = g_proxy_shadow_mount_can_eject;
+ iface->unmount = g_proxy_shadow_mount_unmount;
+ iface->unmount_finish = g_proxy_shadow_mount_unmount_finish;
+ iface->eject = g_proxy_shadow_mount_eject;
+ iface->eject_finish = g_proxy_shadow_mount_eject_finish;
+ iface->guess_content_type = g_proxy_shadow_mount_guess_content_type;
+ iface->guess_content_type_finish = g_proxy_shadow_mount_guess_content_type_finish;
+ iface->guess_content_type_sync = g_proxy_shadow_mount_guess_content_type_sync;
+}
+
+void
+g_proxy_shadow_mount_register (GIOModule *module)
+{
+ g_proxy_shadow_mount_register_type (G_TYPE_MODULE (module));
+}
+
+typedef struct {
+ const char *signal_name;
+ GObject *object;
+ GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+ if (data->other_object != NULL)
+ {
+ g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+ g_object_unref (data->other_object);
+ }
+ else
+ {
+ g_signal_emit_by_name (data->object, data->signal_name);
+ }
+ g_object_unref (data->object);
+ g_free (data);
+
+ return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+ SignalEmitIdleData *data;
+
+ data = g_new0 (SignalEmitIdleData, 1);
+ data->signal_name = signal_name;
+ data->object = g_object_ref (G_OBJECT (object));
+ data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+ g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}
diff --git a/trunk/monitor/proxy/gproxyshadowmount.h b/trunk/monitor/proxy/gproxyshadowmount.h
new file mode 100644
index 00000000..d099f9da
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyshadowmount.h
@@ -0,0 +1,59 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_SHADOW_MOUNT_H__
+#define __G_PROXY_SHADOW_MOUNT_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_SHADOW_MOUNT (g_proxy_shadow_mount_get_type ())
+#define G_PROXY_SHADOW_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMount))
+#define G_PROXY_SHADOW_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_SHADOW_MOUNT, GProxyShadowMountClass))
+#define G_IS_PROXY_SHADOW_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_SHADOW_MOUNT))
+#define G_IS_PROXY_SHADOW_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_SHADOW_MOUNT))
+
+typedef struct _GProxyShadowMountClass GProxyShadowMountClass;
+
+struct _GProxyShadowMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_shadow_mount_get_type (void) G_GNUC_CONST;
+void g_proxy_shadow_mount_register (GIOModule *module);
+GProxyShadowMount *g_proxy_shadow_mount_new (GProxyVolumeMonitor *volume_monitor,
+ GProxyVolume *volume,
+ GMount *real_mount);
+GMount *g_proxy_shadow_mount_get_real_mount (GProxyShadowMount *mount);
+GFile *g_proxy_shadow_mount_get_activation_root (GProxyShadowMount *mount);
+gboolean g_proxy_shadow_mount_has_mount_path (GProxyShadowMount *mount,
+ const char *mount_path);
+void g_proxy_shadow_mount_remove (GProxyShadowMount *mount);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_SHADOW_MOUNT_H__ */
diff --git a/trunk/monitor/proxy/gproxyvolume.c b/trunk/monitor/proxy/gproxyvolume.c
new file mode 100644
index 00000000..2d171219
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyvolume.c
@@ -0,0 +1,1229 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include <gdbusutils.h>
+
+#include "gproxydrive.h"
+#include "gproxyvolume.h"
+#include "gproxymount.h"
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+/* Protects all fields of GProxyVolume that can change */
+G_LOCK_DEFINE_STATIC(proxy_volume);
+
+struct _GProxyVolume {
+ GObject parent;
+
+ GProxyVolumeMonitor *volume_monitor;
+
+ /* non-NULL only if activation_uri != NULL */
+ GVolumeMonitor *union_monitor;
+
+ char *id;
+ char *name;
+ char *uuid;
+ char *activation_uri;
+ GIcon *icon;
+ char *drive_id;
+ char *mount_id;
+ GHashTable *identifiers;
+
+ gboolean can_mount;
+ gboolean should_automount;
+
+ GProxyShadowMount *shadow_mount;
+
+ GHashTable *hash_mount_op_id_to_data;
+};
+
+static void g_proxy_volume_volume_iface_init (GVolumeIface *iface);
+
+#define _G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \
+ const GInterfaceInfo g_implement_interface_info = { \
+ (GInterfaceInitFunc) iface_init, NULL, NULL \
+ }; \
+ g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyVolume, g_proxy_volume, G_TYPE_OBJECT, 0,
+ _G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_VOLUME,
+ g_proxy_volume_volume_iface_init))
+
+
+static void union_monitor_mount_added (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume);
+
+static void update_shadow_mount (GProxyVolume *volume);
+
+GProxyShadowMount *
+g_proxy_volume_get_shadow_mount (GProxyVolume *volume)
+{
+ if (volume->shadow_mount != NULL)
+ return g_object_ref (volume->shadow_mount);
+ else
+ return NULL;
+}
+
+static void
+g_proxy_volume_finalize (GObject *object)
+{
+ GProxyVolume *volume;
+
+ volume = G_PROXY_VOLUME (object);
+
+ g_free (volume->id);
+ g_free (volume->name);
+ g_free (volume->uuid);
+ g_free (volume->activation_uri);
+ if (volume->icon != NULL)
+ g_object_unref (volume->icon);
+ g_free (volume->drive_id);
+ g_free (volume->mount_id);
+ if (volume->identifiers != NULL)
+ g_hash_table_unref (volume->identifiers);
+
+ if (volume->shadow_mount != NULL)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ }
+
+ if (volume->union_monitor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_added, volume);
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_removed, volume);
+ g_signal_handlers_disconnect_by_func (volume->union_monitor, union_monitor_mount_changed, volume);
+ g_object_unref (volume->union_monitor);
+ }
+
+ if (volume->volume_monitor != NULL)
+ {
+ g_object_unref (volume->volume_monitor);
+ }
+
+ g_hash_table_unref (volume->hash_mount_op_id_to_data);
+
+ if (G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_proxy_volume_parent_class)->finalize) (object);
+}
+
+static void
+g_proxy_volume_class_init (GProxyVolumeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_proxy_volume_finalize;
+}
+
+static void
+g_proxy_volume_class_finalize (GProxyVolumeClass *klass)
+{
+}
+
+static void
+g_proxy_volume_init (GProxyVolume *proxy_volume)
+{
+ proxy_volume->hash_mount_op_id_to_data = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+GProxyVolume *
+g_proxy_volume_new (GProxyVolumeMonitor *volume_monitor)
+{
+ GProxyVolume *volume;
+ volume = g_object_new (G_TYPE_PROXY_VOLUME, NULL);
+ volume->volume_monitor = g_object_ref (volume_monitor);
+ g_object_set_data (G_OBJECT (volume),
+ "g-proxy-volume-volume-monitor-name",
+ (gpointer) g_type_name (G_TYPE_FROM_INSTANCE (volume_monitor)));
+ return volume;
+}
+
+
+static void
+union_monitor_mount_added (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
+{
+ update_shadow_mount (volume);
+}
+
+static void
+union_monitor_mount_removed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
+{
+ update_shadow_mount (volume);
+}
+
+static void
+union_monitor_mount_changed (GVolumeMonitor *union_monitor,
+ GMount *mount,
+ GProxyVolume *volume)
+{
+ if (volume->shadow_mount != NULL)
+ {
+ GMount *real_mount;
+ real_mount = g_proxy_shadow_mount_get_real_mount (volume->shadow_mount);
+ if (mount == real_mount)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "changed", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-changed", volume->shadow_mount);
+ }
+ g_object_unref (real_mount);
+ }
+}
+
+static void
+update_shadow_mount (GProxyVolume *volume)
+{
+ GFile *activation_root;
+ GList *mounts;
+ GList *l;
+ GMount *mount_to_shadow;
+
+ activation_root = NULL;
+ mount_to_shadow = NULL;
+
+ if (volume->activation_uri == NULL)
+ goto out;
+
+ activation_root = g_file_new_for_uri (volume->activation_uri);
+
+ if (volume->union_monitor == NULL)
+ {
+ volume->union_monitor = g_volume_monitor_get ();
+ g_signal_connect (volume->union_monitor, "mount-added", (GCallback) union_monitor_mount_added, volume);
+ g_signal_connect (volume->union_monitor, "mount-removed", (GCallback) union_monitor_mount_removed, volume);
+ g_signal_connect (volume->union_monitor, "mount-changed", (GCallback) union_monitor_mount_changed, volume);
+ }
+
+ mounts = g_volume_monitor_get_mounts (volume->union_monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = G_MOUNT (l->data);
+ GFile *mount_root;
+
+ /* don't consider our (possibly) existing shadow mount */
+ if (G_IS_PROXY_SHADOW_MOUNT (mount))
+ continue;
+
+ mount_root = g_mount_get_root (mount);
+ if (g_file_has_prefix (activation_root, mount_root))
+ {
+ mount_to_shadow = g_object_ref (mount);
+ break;
+ }
+ }
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ if (mount_to_shadow != NULL)
+ {
+ /* there's now a mount to shadow, if we don't have a GProxyShadowMount then create one */
+ if (volume->shadow_mount == NULL)
+ {
+ volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+ volume,
+ mount_to_shadow);
+ signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+ }
+ else
+ {
+ GFile *current_activation_root;
+
+ /* we have a GProxyShadowMount already. However, we need to replace it if the
+ * activation root has changed.
+ */
+ current_activation_root = g_proxy_shadow_mount_get_activation_root (volume->shadow_mount);
+ if (!g_file_equal (current_activation_root, activation_root))
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ volume->shadow_mount = NULL;
+
+ volume->shadow_mount = g_proxy_shadow_mount_new (volume->volume_monitor,
+ volume,
+ mount_to_shadow);
+ signal_emit_in_idle (volume->volume_monitor, "mount-added", volume->shadow_mount);
+ }
+ g_object_unref (current_activation_root);
+ }
+ }
+ else
+ {
+ /* no mount to shadow; if we have a GProxyShadowMount then remove it */
+ if (volume->shadow_mount != NULL)
+ {
+ signal_emit_in_idle (volume->shadow_mount, "unmounted", NULL);
+ signal_emit_in_idle (volume->volume_monitor, "mount-removed", volume->shadow_mount);
+ g_proxy_shadow_mount_remove (volume->shadow_mount);
+ g_object_unref (volume->shadow_mount);
+ volume->shadow_mount = NULL;
+ }
+ }
+
+ out:
+
+ if (activation_root != NULL)
+ g_object_unref (activation_root);
+
+ if (mount_to_shadow != NULL)
+ g_object_unref (mount_to_shadow);
+}
+
+static gboolean
+update_shadow_mount_in_idle_do (GProxyVolume *volume)
+{
+ update_shadow_mount (volume);
+ g_object_unref (volume);
+ return FALSE;
+}
+
+static void
+update_shadow_mount_in_idle (GProxyVolume *volume)
+{
+ g_idle_add ((GSourceFunc) update_shadow_mount_in_idle_do, g_object_ref (volume));
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string activation_uri
+ * boolean can-mount
+ * boolean should-automount
+ * string drive-id
+ * string mount-id
+ * dict:string->string identifiers
+ */
+
+void g_proxy_volume_update (GProxyVolume *volume,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter iter_struct;
+ const char *id;
+ const char *name;
+ const char *gicon_data;
+ const char *uuid;
+ const char *activation_uri;
+ const char *drive_id;
+ const char *mount_id;
+ dbus_bool_t can_mount;
+ dbus_bool_t should_automount;
+ GHashTable *identifiers;
+
+ dbus_message_iter_recurse (iter, &iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &name);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &gicon_data);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &uuid);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &activation_uri);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &can_mount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &should_automount);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &drive_id);
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &mount_id);
+ dbus_message_iter_next (&iter_struct);
+
+ identifiers = _get_identifiers (&iter_struct);
+ dbus_message_iter_next (&iter_struct);
+
+ if (volume->id != NULL && strcmp (volume->id, id) != 0)
+ {
+ g_warning ("id mismatch during update of volume");
+ goto out;
+ }
+
+ if (strlen (name) == 0)
+ name = NULL;
+ if (strlen (uuid) == 0)
+ uuid = NULL;
+ if (strlen (activation_uri) == 0)
+ activation_uri = NULL;
+
+ /* out with the old */
+ g_free (volume->id);
+ g_free (volume->name);
+ g_free (volume->uuid);
+ g_free (volume->activation_uri);
+ if (volume->icon != NULL)
+ g_object_unref (volume->icon);
+ g_free (volume->drive_id);
+ g_free (volume->mount_id);
+ if (volume->identifiers != NULL)
+ g_hash_table_unref (volume->identifiers);
+
+ /* in with the new */
+ volume->id = g_strdup (id);
+ volume->name = g_strdup (name);
+ volume->uuid = g_strdup (uuid);
+ volume->activation_uri = g_strdup (activation_uri);
+ if (*gicon_data == 0)
+ volume->icon = NULL;
+ else
+ volume->icon = g_icon_new_for_string (gicon_data, NULL);
+ volume->drive_id = g_strdup (drive_id);
+ volume->mount_id = g_strdup (mount_id);
+ volume->can_mount = can_mount;
+ volume->should_automount = should_automount;
+ volume->identifiers = identifiers != NULL ? g_hash_table_ref (identifiers) : NULL;
+
+ /* this calls into the union monitor; do it in idle to avoid locking issues */
+ update_shadow_mount_in_idle (volume);
+
+ out:
+ g_hash_table_unref (identifiers);
+}
+
+const char *
+g_proxy_volume_get_id (GProxyVolume *volume)
+{
+ return volume->id;
+}
+
+static GIcon *
+g_proxy_volume_get_icon (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GIcon *icon;
+
+ G_LOCK (proxy_volume);
+ icon = proxy_volume->icon != NULL ? g_object_ref (proxy_volume->icon) : NULL;
+ G_UNLOCK (proxy_volume);
+ return icon;
+}
+
+static char *
+g_proxy_volume_get_name (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *name;
+
+ G_LOCK (proxy_volume);
+ name = g_strdup (proxy_volume->name);
+ G_UNLOCK (proxy_volume);
+ return name;
+}
+
+static char *
+g_proxy_volume_get_uuid (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *uuid;
+
+ G_LOCK (proxy_volume);
+ uuid = g_strdup (proxy_volume->uuid);
+ G_UNLOCK (proxy_volume);
+ return uuid;
+}
+
+static gboolean
+g_proxy_volume_can_mount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = proxy_volume->can_mount;
+ G_UNLOCK (proxy_volume);
+ return res;
+}
+
+static gboolean
+g_proxy_volume_can_eject (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = FALSE;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ {
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ if (drive != NULL)
+ {
+ res = g_drive_can_eject (G_DRIVE (drive));
+ g_object_unref (drive);
+ }
+ }
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static gboolean
+g_proxy_volume_should_automount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = proxy_volume->should_automount;
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static GDrive *
+g_proxy_volume_get_drive (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+
+ G_LOCK (proxy_volume);
+ drive = NULL;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ G_UNLOCK (proxy_volume);
+
+ return drive != NULL ? G_DRIVE (drive) : NULL;
+}
+
+static GMount *
+g_proxy_volume_get_mount (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GMount *mount;
+
+ mount = NULL;
+
+ G_LOCK (proxy_volume);
+
+ if (proxy_volume->shadow_mount != NULL)
+ {
+ mount = g_object_ref (proxy_volume->shadow_mount);
+ }
+ else if (proxy_volume->mount_id != NULL && strlen (proxy_volume->mount_id) > 0)
+ {
+ GProxyMount *proxy_mount;
+ proxy_mount = g_proxy_volume_monitor_get_mount_for_id (proxy_volume->volume_monitor,
+ proxy_volume->mount_id);
+ if (proxy_mount != NULL)
+ mount = G_MOUNT (proxy_mount);
+ }
+ G_UNLOCK (proxy_volume);
+
+ return mount;
+}
+
+typedef struct {
+ GObject *object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} EjectWrapperOp;
+
+static void
+eject_wrapper_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EjectWrapperOp *data = user_data;
+ data->callback (data->object, res, data->user_data);
+ g_object_unref (data->object);
+ g_free (data);
+}
+
+static void
+g_proxy_volume_eject (GVolume *volume,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+
+ drive = NULL;
+ G_LOCK (proxy_volume);
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ {
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ }
+ G_UNLOCK (proxy_volume);
+
+ if (drive != NULL)
+ {
+ EjectWrapperOp *data;
+ data = g_new0 (EjectWrapperOp, 1);
+ data->object = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ g_drive_eject (G_DRIVE (drive), flags, cancellable, eject_wrapper_callback, data);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+g_proxy_volume_eject_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GProxyDrive *drive;
+ gboolean res;
+
+ G_LOCK (proxy_volume);
+ res = TRUE;
+ drive = NULL;
+ if (proxy_volume->drive_id != NULL && strlen (proxy_volume->drive_id) > 0)
+ drive = g_proxy_volume_monitor_get_drive_for_id (proxy_volume->volume_monitor,
+ proxy_volume->drive_id);
+ G_UNLOCK (proxy_volume);
+
+ if (drive != NULL)
+ {
+ res = g_drive_eject_finish (G_DRIVE (drive), result, error);
+ g_object_unref (drive);
+ }
+
+ return res;
+}
+
+static char *
+g_proxy_volume_get_identifier (GVolume *volume,
+ const char *kind)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ char *res;
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->identifiers != NULL)
+ res = g_strdup (g_hash_table_lookup (proxy_volume->identifiers, kind));
+ else
+ res = NULL;
+ G_UNLOCK (proxy_volume);
+
+ return res;
+}
+
+static void
+add_identifier_key (const char *key, const char *value, GPtrArray *res)
+{
+ g_ptr_array_add (res, g_strdup (key));
+}
+
+static char **
+g_proxy_volume_enumerate_identifiers (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ GPtrArray *res;
+
+ res = g_ptr_array_new ();
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->identifiers != NULL)
+ g_hash_table_foreach (proxy_volume->identifiers, (GHFunc) add_identifier_key, res);
+ G_UNLOCK (proxy_volume);
+
+ /* Null-terminate */
+ g_ptr_array_add (res, NULL);
+
+ return (char **) g_ptr_array_free (res, FALSE);
+}
+
+typedef struct {
+ GProxyVolume *volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+ gchar *cancellation_id;
+ GCancellable *cancellable;
+ gulong cancelled_handler_id;
+
+ gchar *mount_op_id;
+ GMountOperation *mount_operation;
+ gulong reply_handler_id;
+} DBusOp;
+
+static void
+mount_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ if (data->cancelled_handler_id > 0)
+ g_signal_handler_disconnect (data->cancellable, data->cancelled_handler_id);
+
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ {
+ GSimpleAsyncResult *simple;
+
+ if (error != NULL)
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ error);
+ else
+ simple = g_simple_async_result_new (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ NULL);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ }
+
+ /* free DBusOp */
+ if (strlen (data->mount_op_id) > 0)
+ g_hash_table_remove (data->volume->hash_mount_op_id_to_data, data->mount_op_id);
+ g_object_unref (data->volume);
+
+ g_free (data->mount_op_id);
+ if (data->reply_handler_id > 0)
+ g_signal_handler_disconnect (data->mount_operation, data->reply_handler_id);
+ if (data->mount_operation != NULL)
+ g_object_unref (data->mount_operation);
+
+ g_free (data->cancellation_id);
+ if (data->cancellable != NULL)
+ g_object_unref (data->cancellable);
+
+ g_free (data);
+}
+
+typedef struct
+{
+ GProxyVolume *enclosing_volume;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+} ForeignMountOp;
+
+static void
+mount_foreign_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ForeignMountOp *data = user_data;
+ data->callback (G_OBJECT (data->enclosing_volume), res, data->user_data);
+ g_object_unref (data->enclosing_volume);
+ g_free (data);
+}
+
+static void
+cancel_operation_reply_cb (DBusMessage *reply,
+ GError *error,
+ gpointer user_data)
+{
+ if (error != NULL)
+ {
+ g_warning ("Error from CancelOperation(): %s", error->message);
+ }
+}
+
+static void
+mount_cancelled (GCancellable *cancellable,
+ gpointer user_data)
+{
+ DBusOp *data = user_data;
+ GSimpleAsyncResult *simple;
+ DBusConnection *connection;
+ DBusMessage *message;
+ const char *name;
+
+ G_LOCK (proxy_volume);
+
+ simple = g_simple_async_result_new_error (G_OBJECT (data->volume),
+ data->callback,
+ data->user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+
+ /* Now tell the remote volume monitor that the op has been cancelled */
+ connection = g_proxy_volume_monitor_get_dbus_connection (data->volume->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (data->volume->volume_monitor);
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "CancelOperation");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_INVALID);
+
+ G_UNLOCK (proxy_volume);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) cancel_operation_reply_cb,
+ NULL);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+}
+
+static void
+g_proxy_volume_mount (GVolume *volume,
+ GMountMountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+
+ G_LOCK (proxy_volume);
+ if (proxy_volume->activation_uri != NULL)
+ {
+ ForeignMountOp *data;
+ GFile *root;
+
+ data = g_new0 (ForeignMountOp, 1);
+ data->enclosing_volume = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ root = g_file_new_for_uri (proxy_volume->activation_uri);
+
+ G_UNLOCK (proxy_volume);
+
+ g_file_mount_enclosing_volume (root,
+ flags,
+ mount_operation,
+ cancellable,
+ mount_foreign_callback,
+ data);
+
+ g_object_unref (root);
+ }
+ else
+ {
+ DBusOp *data;
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ dbus_uint32_t _flags = flags;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new_error (G_OBJECT (volume),
+ callback,
+ user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ _("Operation was cancelled"));
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ G_UNLOCK (proxy_volume);
+ goto out;
+ }
+
+ data = g_new0 (DBusOp, 1);
+ data->volume = g_object_ref (volume);
+ data->callback = callback;
+ data->user_data = user_data;
+ if (cancellable != NULL)
+ {
+ data->cancellation_id = g_strdup_printf ("%p", cancellable);
+ data->cancellable = g_object_ref (cancellable);
+ data->cancelled_handler_id = g_signal_connect (data->cancellable,
+ "cancelled",
+ G_CALLBACK (mount_cancelled),
+ data);
+ }
+ else
+ {
+ data->cancellation_id = g_strdup ("");
+ }
+
+ if (mount_operation != NULL)
+ {
+ data->mount_op_id = g_strdup_printf ("%p", mount_operation);
+ data->mount_operation = g_object_ref (mount_operation);
+ g_hash_table_insert (proxy_volume->hash_mount_op_id_to_data,
+ data->mount_op_id,
+ data);
+ }
+ else
+ {
+ data->mount_op_id = g_strdup ("");
+ }
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (proxy_volume->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (proxy_volume->volume_monitor);
+
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "VolumeMount");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(proxy_volume->id),
+ DBUS_TYPE_STRING,
+ &(data->cancellation_id),
+ DBUS_TYPE_UINT32,
+ &_flags,
+ DBUS_TYPE_STRING,
+ &(data->mount_op_id),
+ DBUS_TYPE_INVALID);
+ G_UNLOCK (proxy_volume);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ 30 * 60 * 1000, /* 30 minute timeout */
+ (GAsyncDBusCallback) mount_cb,
+ data);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+ }
+
+ out:
+ ;
+}
+
+
+static void
+mount_op_reply_cb (DBusMessage *reply,
+ GError *error,
+ DBusOp *data)
+{
+ if (error != NULL)
+ {
+ g_warning ("Error from MountOpReply(): %s", error->message);
+ }
+}
+
+static void
+mount_operation_reply (GMountOperation *mount_operation,
+ GMountOperationResult result,
+ gpointer user_data)
+{
+ DBusOp *data = user_data;
+ DBusConnection *connection;
+ const char *name;
+ DBusMessage *message;
+ const char *user_name;
+ const char *domain;
+ const char *password;
+ char *encoded_password;
+ dbus_uint32_t password_save;
+ dbus_uint32_t choice;
+ dbus_bool_t anonymous;
+
+ connection = g_proxy_volume_monitor_get_dbus_connection (data->volume->volume_monitor);
+ name = g_proxy_volume_monitor_get_dbus_name (data->volume->volume_monitor);
+
+ user_name = g_mount_operation_get_username (mount_operation);
+ domain = g_mount_operation_get_domain (mount_operation);
+ password = g_mount_operation_get_password (mount_operation);
+ password_save = g_mount_operation_get_password_save (mount_operation);
+ choice = g_mount_operation_get_choice (mount_operation);
+ anonymous = g_mount_operation_get_anonymous (mount_operation);
+
+ if (user_name == NULL)
+ user_name = "";
+ if (domain == NULL)
+ domain = "";
+ if (password == NULL)
+ password = "";
+
+ /* NOTE: this is not to add "security", it's merely to prevent accidental exposure
+ * of passwords when running dbus-monitor
+ */
+ encoded_password = g_base64_encode ((const guchar *) password, (gsize) (strlen (password) + 1));
+
+ message = dbus_message_new_method_call (name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountOpReply");
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING,
+ &(data->volume->id),
+ DBUS_TYPE_STRING,
+ &(data->mount_op_id),
+ DBUS_TYPE_INT32,
+ &result,
+ DBUS_TYPE_STRING,
+ &user_name,
+ DBUS_TYPE_STRING,
+ &domain,
+ DBUS_TYPE_STRING,
+ &encoded_password,
+ DBUS_TYPE_INT32,
+ &password_save,
+ DBUS_TYPE_INT32,
+ &choice,
+ DBUS_TYPE_BOOLEAN,
+ &anonymous,
+ DBUS_TYPE_INVALID);
+
+ _g_dbus_connection_call_async (connection,
+ message,
+ -1,
+ (GAsyncDBusCallback) mount_op_reply_cb,
+ data);
+
+ g_free (encoded_password);
+ dbus_message_unref (message);
+ dbus_connection_unref (connection);
+}
+
+void
+g_proxy_volume_handle_mount_op_ask_password (GProxyVolume *volume,
+ DBusMessageIter *iter)
+{
+ const char *mount_op_id;
+ const char *message;
+ const char *default_user;
+ const char *default_domain;
+ dbus_int32_t flags;
+ DBusOp *data;
+
+ dbus_message_iter_get_basic (iter, &mount_op_id);
+ dbus_message_iter_next (iter);
+
+ dbus_message_iter_get_basic (iter, &message);
+ dbus_message_iter_next (iter);
+
+ dbus_message_iter_get_basic (iter, &default_user);
+ dbus_message_iter_next (iter);
+
+ dbus_message_iter_get_basic (iter, &default_domain);
+ dbus_message_iter_next (iter);
+
+ dbus_message_iter_get_basic (iter, &flags);
+ dbus_message_iter_next (iter);
+
+ data = g_hash_table_lookup (volume->hash_mount_op_id_to_data, mount_op_id);
+
+ /* since eavesdropping is enabled on the session bus we get this signal even if it
+ * is for another application; so silently ignore it if it's not for us
+ */
+ if (data == NULL)
+ goto out;
+
+ if (data->reply_handler_id == 0)
+ {
+ data->reply_handler_id = g_signal_connect (data->mount_operation,
+ "reply",
+ G_CALLBACK (mount_operation_reply),
+ data);
+ }
+
+ g_signal_emit_by_name (data->mount_operation,
+ "ask-password",
+ message,
+ default_user,
+ default_domain,
+ flags);
+
+ out:
+ ;
+}
+
+void
+g_proxy_volume_handle_mount_op_ask_question (GProxyVolume *volume,
+ DBusMessageIter *iter)
+{
+ const char *mount_op_id;
+ const char *message;
+ GPtrArray *choices;
+ DBusMessageIter iter_array;
+ DBusOp *data;
+
+ choices = NULL;
+
+ dbus_message_iter_get_basic (iter, &mount_op_id);
+ dbus_message_iter_next (iter);
+
+ dbus_message_iter_get_basic (iter, &message);
+ dbus_message_iter_next (iter);
+
+ choices = g_ptr_array_new ();
+ dbus_message_iter_recurse (iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ const char *choice;
+ dbus_message_iter_get_basic (&iter_array, &choice);
+ dbus_message_iter_next (&iter_array);
+
+ g_ptr_array_add (choices, g_strdup (choice));
+ }
+ g_ptr_array_add (choices, NULL);
+
+ data = g_hash_table_lookup (volume->hash_mount_op_id_to_data, mount_op_id);
+
+ /* since eavesdropping is enabled on the session bus we get this signal even if it
+ * is for another application; so silently ignore it if it's not for us
+ */
+ if (data == NULL)
+ goto out;
+
+ if (data->reply_handler_id == 0)
+ {
+ data->reply_handler_id = g_signal_connect (data->mount_operation,
+ "reply",
+ G_CALLBACK (mount_operation_reply),
+ data);
+ }
+
+ g_signal_emit_by_name (data->mount_operation,
+ "ask-question",
+ message,
+ choices->pdata);
+
+ out:
+ g_ptr_array_free (choices, TRUE);
+}
+
+void
+g_proxy_volume_handle_mount_op_aborted (GProxyVolume *volume,
+ DBusMessageIter *iter)
+{
+ const char *mount_op_id;
+ DBusOp *data;
+
+ dbus_message_iter_get_basic (iter, &mount_op_id);
+ dbus_message_iter_next (iter);
+
+ data = g_hash_table_lookup (volume->hash_mount_op_id_to_data, mount_op_id);
+
+ /* since eavesdropping is enabled on the session bus we get this signal even if it
+ * is for another application; so silently ignore it if it's not for us
+ */
+ if (data == NULL)
+ goto out;
+
+ g_signal_emit_by_name (data->mount_operation, "aborted");
+
+ out:
+ ;
+}
+
+static gboolean
+g_proxy_volume_mount_finish (GVolume *volume,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+ return TRUE;
+}
+
+static GFile *
+g_proxy_volume_get_activation_root (GVolume *volume)
+{
+ GProxyVolume *proxy_volume = G_PROXY_VOLUME (volume);
+ if (proxy_volume->activation_uri == NULL)
+ return NULL;
+ else
+ return g_file_new_for_uri (proxy_volume->activation_uri);
+}
+
+static void
+g_proxy_volume_volume_iface_init (GVolumeIface *iface)
+{
+ iface->get_name = g_proxy_volume_get_name;
+ iface->get_icon = g_proxy_volume_get_icon;
+ iface->get_uuid = g_proxy_volume_get_uuid;
+ iface->get_drive = g_proxy_volume_get_drive;
+ iface->get_mount = g_proxy_volume_get_mount;
+ iface->can_mount = g_proxy_volume_can_mount;
+ iface->can_eject = g_proxy_volume_can_eject;
+ iface->should_automount = g_proxy_volume_should_automount;
+ iface->mount_fn = g_proxy_volume_mount;
+ iface->mount_finish = g_proxy_volume_mount_finish;
+ iface->eject = g_proxy_volume_eject;
+ iface->eject_finish = g_proxy_volume_eject_finish;
+ iface->get_identifier = g_proxy_volume_get_identifier;
+ iface->enumerate_identifiers = g_proxy_volume_enumerate_identifiers;
+ iface->get_activation_root = g_proxy_volume_get_activation_root;
+}
+
+void
+g_proxy_volume_register (GIOModule *module)
+{
+ g_proxy_volume_register_type (G_TYPE_MODULE (module));
+}
+
+typedef struct {
+ const char *signal_name;
+ GObject *object;
+ GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+ if (data->other_object != NULL)
+ {
+ g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+ g_object_unref (data->other_object);
+ }
+ else
+ {
+ g_signal_emit_by_name (data->object, data->signal_name);
+ }
+ g_object_unref (data->object);
+ g_free (data);
+
+ return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+ SignalEmitIdleData *data;
+
+ data = g_new0 (SignalEmitIdleData, 1);
+ data->signal_name = signal_name;
+ data->object = g_object_ref (G_OBJECT (object));
+ data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+ g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}
diff --git a/trunk/monitor/proxy/gproxyvolume.h b/trunk/monitor/proxy/gproxyvolume.h
new file mode 100644
index 00000000..ea2d98d8
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyvolume.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_VOLUME_H__
+#define __G_PROXY_VOLUME_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyshadowmount.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_VOLUME (g_proxy_volume_get_type ())
+#define G_PROXY_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_VOLUME, GProxyVolume))
+#define G_PROXY_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_VOLUME, GProxyVolumeClass))
+#define G_IS_PROXY_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_VOLUME))
+#define G_IS_PROXY_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_VOLUME))
+
+typedef struct _GProxyVolumeClass GProxyVolumeClass;
+
+struct _GProxyVolumeClass {
+ GObjectClass parent_class;
+};
+
+GType g_proxy_volume_get_type (void) G_GNUC_CONST;
+GProxyVolume *g_proxy_volume_new (GProxyVolumeMonitor *volume_monitor);
+void g_proxy_volume_update (GProxyVolume *volume,
+ DBusMessageIter *iter);
+const char *g_proxy_volume_get_id (GProxyVolume *volume);
+void g_proxy_volume_register (GIOModule *module);
+
+GProxyShadowMount *g_proxy_volume_get_shadow_mount (GProxyVolume *volume);
+
+void g_proxy_volume_handle_mount_op_ask_password (GProxyVolume *volume,
+ DBusMessageIter *iter);
+
+void g_proxy_volume_handle_mount_op_ask_question (GProxyVolume *volume,
+ DBusMessageIter *iter);
+
+void g_proxy_volume_handle_mount_op_aborted (GProxyVolume *volume,
+ DBusMessageIter *iter);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_VOLUME_H__ */
diff --git a/trunk/monitor/proxy/gproxyvolumemonitor.c b/trunk/monitor/proxy/gproxyvolumemonitor.c
new file mode 100644
index 00000000..f836c19d
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyvolumemonitor.c
@@ -0,0 +1,1354 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+/* TODO: handle force_rescan in g_mount_guess_content_type(); right now we
+ * just scan in the daemon first time the GMount is seen and
+ * cache that result forever.
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gdbusutils.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxymount.h"
+#include "gproxyvolume.h"
+#include "gproxydrive.h"
+
+G_LOCK_DEFINE_STATIC(proxy_vm);
+
+static DBusConnection *the_session_bus = NULL;
+static gboolean the_session_bus_is_integrated = FALSE;
+static GHashTable *the_volume_monitors = NULL;
+
+struct _GProxyVolumeMonitor {
+ GNativeVolumeMonitor parent;
+ DBusConnection *session_bus;
+
+ GHashTable *drives;
+ GHashTable *volumes;
+ GHashTable *mounts;
+
+ /* The unique D-Bus name of the remote monitor or NULL if disconnected */
+ gchar *unique_name;
+};
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GProxyVolumeMonitor,
+ g_proxy_volume_monitor,
+ G_TYPE_NATIVE_VOLUME_MONITOR,
+ G_TYPE_FLAG_ABSTRACT,
+ {})
+
+static void seed_monitor (GProxyVolumeMonitor *monitor);
+
+static DBusHandlerResult filter_function (DBusConnection *connection, DBusMessage *message, void *user_data);
+
+static void signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object);
+
+static gboolean is_supported (GProxyVolumeMonitorClass *klass);
+
+/* The is_supported API is kinda lame and doesn't pass in the class,
+ so we work around this with this hack */
+typedef gboolean (*is_supported_func) (void);
+
+static GProxyVolumeMonitorClass *is_supported_classes[10] = { NULL };
+static gboolean is_supported_0 (void) { return is_supported (is_supported_classes[0]); };
+static gboolean is_supported_1 (void) { return is_supported (is_supported_classes[1]); };
+static gboolean is_supported_2 (void) { return is_supported (is_supported_classes[2]); };
+static gboolean is_supported_3 (void) { return is_supported (is_supported_classes[3]); };
+static gboolean is_supported_4 (void) { return is_supported (is_supported_classes[4]); };
+static gboolean is_supported_5 (void) { return is_supported (is_supported_classes[5]); };
+static gboolean is_supported_6 (void) { return is_supported (is_supported_classes[6]); };
+static gboolean is_supported_7 (void) { return is_supported (is_supported_classes[7]); };
+static gboolean is_supported_8 (void) { return is_supported (is_supported_classes[8]); };
+static gboolean is_supported_9 (void) { return is_supported (is_supported_classes[9]); };
+static is_supported_func is_supported_funcs[] = {
+ is_supported_0, is_supported_1, is_supported_2, is_supported_3,
+ is_supported_4, is_supported_5, is_supported_6, is_supported_7,
+ is_supported_8, is_supported_9,
+ NULL
+};
+
+static char *
+get_match_rule_for_signals (GProxyVolumeMonitor *monitor)
+{
+ return g_strdup_printf ("type='signal',"
+ "interface='org.gtk.Private.RemoteVolumeMonitor',"
+ "sender='%s',",
+ g_proxy_volume_monitor_get_dbus_name (monitor));
+}
+
+static char *
+get_match_rule_for_name_owner_changed (GProxyVolumeMonitor *monitor)
+{
+ return g_strdup_printf ("type='signal',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',"
+ "arg0='%s'",
+ g_proxy_volume_monitor_get_dbus_name (monitor));
+}
+
+static void
+g_proxy_volume_monitor_finalize (GObject *object)
+{
+ GProxyVolumeMonitor *monitor;
+ DBusError dbus_error;
+ char *match_rule;
+ GObjectClass *parent_class;
+
+ /* since GProxyVolumeMonitor is a non-instantiatable type we're dealing with a
+ * sub-type here. So we need to look at the grandparent sub-type to get the
+ * parent class for GProxyVolumeMonitor */
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (
+ g_type_class_peek_parent (G_OBJECT_GET_CLASS (object))));
+
+ monitor = G_PROXY_VOLUME_MONITOR (object);
+
+ g_hash_table_unref (monitor->drives);
+ g_hash_table_unref (monitor->volumes);
+ g_hash_table_unref (monitor->mounts);
+
+ g_free (monitor->unique_name);
+
+ dbus_connection_remove_filter (monitor->session_bus, filter_function, monitor);
+
+ match_rule = get_match_rule_for_signals (monitor);
+ dbus_error_init (&dbus_error);
+ dbus_bus_remove_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("cannot remove match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+
+ match_rule = get_match_rule_for_name_owner_changed (monitor);
+ dbus_error_init (&dbus_error);
+ dbus_bus_remove_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("cannot remove match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+
+ dbus_connection_unref (monitor->session_bus);
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+static void
+g_proxy_volume_monitor_dispose (GObject *object)
+{
+ GProxyVolumeMonitor *monitor;
+ GObjectClass *parent_class;
+
+ /* since GProxyVolumeMonitor is a non-instantiatable type we're dealing with a
+ * sub-type here. So we need to look at the grandparent sub-type to get the
+ * parent class for GProxyVolumeMonitor */
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (
+ g_type_class_peek_parent (G_OBJECT_GET_CLASS (object))));
+
+ monitor = G_PROXY_VOLUME_MONITOR (object);
+
+ /* Clear all objects to avoid circular dependencies keeping things alive.
+ * Note that atm we're keeping the union monitor alive, so this won't
+ * actually happen, but better safe than sorry in case we change this
+ * later */
+ g_hash_table_remove_all (monitor->drives);
+ g_hash_table_remove_all (monitor->volumes);
+ g_hash_table_remove_all (monitor->mounts);
+
+ if (parent_class->dispose)
+ parent_class->dispose (object);
+}
+
+
+static GList *
+get_mounts (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyMount *mount;
+ GProxyVolume *volume;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
+ l = g_list_append (l, g_object_ref (mount));
+
+ /* also return shadow mounts */
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ {
+ GProxyShadowMount *shadow_mount;
+ shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+ if (shadow_mount != NULL)
+ l = g_list_append (l, shadow_mount);
+ }
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GList *
+get_volumes (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyVolume *volume;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ l = g_list_append (l, g_object_ref (volume));
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GList *
+get_connected_drives (GVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitor *monitor;
+ GList *l;
+ GHashTableIter hash_iter;
+ GProxyDrive *drive;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+ l = NULL;
+
+ G_LOCK (proxy_vm);
+
+ g_hash_table_iter_init (&hash_iter, monitor->drives);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &drive))
+ l = g_list_append (l, g_object_ref (drive));
+
+ G_UNLOCK (proxy_vm);
+
+ return l;
+}
+
+static GVolume *
+get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GProxyVolumeMonitor *monitor;
+ GHashTableIter hash_iter;
+ GVolume *found_volume;
+ GVolume *volume;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+
+ G_LOCK (proxy_vm);
+
+ found_volume = NULL;
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume) &&
+ found_volume != NULL)
+ {
+ char *_uuid;
+ _uuid = g_volume_get_uuid (volume);
+ if (_uuid != NULL)
+ {
+ if (strcmp (uuid, _uuid) == 0)
+ found_volume = g_object_ref (volume);
+ g_free (_uuid);
+ }
+ }
+
+ G_UNLOCK (proxy_vm);
+
+ return found_volume;
+}
+
+static GMount *
+get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
+{
+ GProxyVolumeMonitor *monitor;
+ GHashTableIter hash_iter;
+ GMount *found_mount;
+ GMount *mount;
+
+ monitor = G_PROXY_VOLUME_MONITOR (volume_monitor);
+
+ G_LOCK (proxy_vm);
+
+ found_mount = NULL;
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount) &&
+ found_mount != NULL)
+ {
+ char *_uuid;
+ _uuid = g_mount_get_uuid (mount);
+ if (_uuid != NULL)
+ {
+ if (strcmp (uuid, _uuid) == 0)
+ found_mount = g_object_ref (mount);
+ g_free (_uuid);
+ }
+ }
+
+ G_UNLOCK (proxy_vm);
+
+ return found_mount;
+}
+
+static GMount *
+get_mount_for_mount_path (const char *mount_path,
+ GCancellable *cancellable)
+{
+ GMount *mount;
+ GProxyVolumeMonitor *volume_monitor;
+ GProxyVolumeMonitorClass *klass;
+ GHashTableIter vm_hash_iter;
+ GHashTableIter vol_hash_iter;
+ GProxyMount *candidate_mount;
+ static GVolumeMonitor *union_monitor = NULL;
+
+ /* There's a problem here insofar that this static method on GNativeVolumeMonitor can
+ * be called *before* any of our monitors are constructed. Since this method doesn't
+ * pass in the class structure we *know* which native remote monitor to use.
+ *
+ * To work around that, we get the singleton GVolumeMonitor... This will trigger
+ * construction of a GUnionVolumeMonitor in gio which will construct the *appropriate*
+ * remote volume monitors to use (it's up to gio to pick which one to use).
+ *
+ * Note that we will *hold* on to this reference effectively making us a resident
+ * module. And effectively keeping volume monitoring alive.
+ *
+ * The reason we hold on to the reference is that otherwise we'd be constructing/destructing
+ * *all* proxy volume monitors (which includes synchronous D-Bus calls to seed the monitor)
+ * every time this method is called.
+ *
+ * Note that *simple* GIO apps that a) don't use volume monitors; and b) don't use the
+ * g_file_find_enclosing_mount() method will never see any volume monitor overhead.
+ */
+
+ /* Note that g_volume_monitor_get() is thread safe. We don't want to call it while
+ * holding the proxy_vm lock since it might end up calling our constructor.
+ */
+ if (union_monitor == NULL)
+ union_monitor = g_volume_monitor_get ();
+
+ mount = NULL;
+
+ G_LOCK (proxy_vm);
+
+ /* First find the native volume monitor if one exists */
+ g_hash_table_iter_init (&vm_hash_iter, the_volume_monitors);
+ while (g_hash_table_iter_next (&vm_hash_iter, NULL, (gpointer) &volume_monitor)) {
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (volume_monitor));
+
+ if (klass->is_native) {
+ /* The see if we've got a mount */
+ g_hash_table_iter_init (&vol_hash_iter, volume_monitor->mounts);
+ while (g_hash_table_iter_next (&vol_hash_iter, NULL, (gpointer) &candidate_mount)) {
+ if (g_proxy_mount_has_mount_path (candidate_mount, mount_path))
+ {
+ mount = g_object_ref (candidate_mount);
+ goto out;
+ }
+ }
+ goto out;
+ }
+ }
+
+ out:
+ G_UNLOCK (proxy_vm);
+ return mount;
+}
+
+static void
+volume_monitor_went_away (gpointer data,
+ GObject *where_the_object_was)
+{
+ GType type = (GType) data;
+ G_LOCK (proxy_vm);
+ g_hash_table_remove (the_volume_monitors, (gpointer) type);
+ G_UNLOCK (proxy_vm);
+}
+
+static GObject *
+g_proxy_volume_monitor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ GProxyVolumeMonitor *monitor;
+ GProxyVolumeMonitorClass *klass;
+ GObjectClass *parent_class;
+ DBusError dbus_error;
+ char *match_rule;
+
+ G_LOCK (proxy_vm);
+
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (g_type_class_peek (type));
+ object = g_hash_table_lookup (the_volume_monitors, (gpointer) type);
+ if (object != NULL)
+ {
+ g_object_ref (object);
+ goto out;
+ }
+
+ /* Invoke parent constructor. */
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (g_type_class_peek (G_TYPE_PROXY_VOLUME_MONITOR));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ object = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ monitor = G_PROXY_VOLUME_MONITOR (object);
+
+ dbus_error_init (&dbus_error);
+ monitor->session_bus = dbus_connection_ref (the_session_bus);
+ monitor->drives = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ monitor->volumes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ monitor->mounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ dbus_connection_add_filter (monitor->session_bus, filter_function, monitor, NULL);
+
+ /* listen to volume monitor signals */
+ match_rule = get_match_rule_for_signals (monitor);
+ dbus_bus_add_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("cannot add match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+
+ /* listen to when the owner of the service appears/disappears */
+ match_rule = get_match_rule_for_name_owner_changed (monitor);
+ dbus_bus_add_match (monitor->session_bus,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("cannot add match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+ g_free (match_rule);
+
+ seed_monitor (monitor);
+
+ g_hash_table_insert (the_volume_monitors, (gpointer) type, object);
+ g_object_weak_ref (G_OBJECT (object), volume_monitor_went_away, (gpointer) type);
+
+ out:
+ G_UNLOCK (proxy_vm);
+ return object;
+}
+
+typedef struct {
+ const char *signal_name;
+ GObject *object;
+ GObject *other_object;
+} SignalEmitIdleData;
+
+static gboolean
+signal_emit_in_idle_do (SignalEmitIdleData *data)
+{
+ if (data->other_object != NULL)
+ {
+ g_signal_emit_by_name (data->object, data->signal_name, data->other_object);
+ g_object_unref (data->other_object);
+ }
+ else
+ {
+ g_signal_emit_by_name (data->object, data->signal_name);
+ }
+ g_object_unref (data->object);
+ g_free (data);
+
+ return FALSE;
+}
+
+static void
+signal_emit_in_idle (gpointer object, const char *signal_name, gpointer other_object)
+{
+ SignalEmitIdleData *data;
+
+ data = g_new0 (SignalEmitIdleData, 1);
+ data->signal_name = signal_name;
+ data->object = g_object_ref (G_OBJECT (object));
+ data->other_object = other_object != NULL ? g_object_ref (G_OBJECT (other_object)) : NULL;
+ g_idle_add ((GSourceFunc) signal_emit_in_idle_do, data);
+}
+
+
+
+static DBusHandlerResult
+filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ GProxyVolumeMonitor *monitor = G_PROXY_VOLUME_MONITOR (user_data);
+ DBusMessageIter iter;
+ const char *id;
+ const char *the_dbus_name;
+ const char *member;
+ GProxyDrive *drive;
+ GProxyVolume *volume;
+ GProxyMount *mount;
+ GProxyVolumeMonitorClass *klass;
+
+ G_LOCK (proxy_vm);
+
+ klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (monitor));
+
+ member = dbus_message_get_member (message);
+
+ if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ GHashTableIter hash_iter;
+ GProxyMount *mount;
+ GProxyVolume *volume;
+ GProxyDrive *drive;
+ const gchar *name;
+ const gchar *old_owner;
+ const gchar *new_owner;
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &old_owner);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &new_owner);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (monitor->unique_name != NULL && g_strcmp0 (new_owner, monitor->unique_name) != 0)
+ {
+ g_warning ("Owner %s of volume monitor %s disconnected from the bus; removing drives/volumes/mounts",
+ monitor->unique_name,
+ klass->dbus_name);
+
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
+ {
+ signal_emit_in_idle (mount, "unmounted", NULL);
+ signal_emit_in_idle (monitor, "mount-removed", mount);
+ }
+ g_hash_table_remove_all (monitor->mounts);
+
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ {
+ signal_emit_in_idle (volume, "removed", NULL);
+ signal_emit_in_idle (monitor, "volume-removed", volume);
+ }
+ g_hash_table_remove_all (monitor->volumes);
+
+ g_hash_table_iter_init (&hash_iter, monitor->drives);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &drive))
+ {
+ signal_emit_in_idle (drive, "disconnected", NULL);
+ signal_emit_in_idle (monitor, "drive-disconnected", drive);
+ }
+ g_hash_table_remove_all (monitor->drives);
+
+ g_free (monitor->unique_name);
+ monitor->unique_name = NULL;
+
+ /* TODO: maybe try to relaunch the monitor? */
+
+ }
+
+ if (strlen (new_owner) > 0 && monitor->unique_name == NULL)
+ {
+ g_warning ("New owner %s for volume monitor %s connected to the bus; seeding drives/volumes/mounts",
+ new_owner,
+ klass->dbus_name);
+
+ seed_monitor (monitor);
+
+ /* emit signals for all the drives/volumes/mounts "added" */
+ g_hash_table_iter_init (&hash_iter, monitor->drives);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &drive))
+ signal_emit_in_idle (monitor, "drive-connected", drive);
+
+ g_hash_table_iter_init (&hash_iter, monitor->volumes);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &volume))
+ signal_emit_in_idle (monitor, "volume-added", volume);
+
+ g_hash_table_iter_init (&hash_iter, monitor->mounts);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &mount))
+ signal_emit_in_idle (monitor, "mount-added", mount);
+ }
+
+ }
+ else if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveConnected") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveDisconnected") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveEjectButton"))
+ {
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "DriveChanged") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ g_proxy_drive_update (drive, &iter);
+ signal_emit_in_idle (drive, "changed", NULL);
+ signal_emit_in_idle (monitor, "drive-changed", drive);
+ }
+ }
+ else if (strcmp (member, "DriveConnected") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive == NULL)
+ {
+ drive = g_proxy_drive_new (monitor);
+ g_proxy_drive_update (drive, &iter);
+ g_hash_table_insert (monitor->drives, g_strdup (g_proxy_drive_get_id (drive)), drive);
+ signal_emit_in_idle (monitor, "drive-connected", drive);
+ }
+ }
+ else if (strcmp (member, "DriveDisconnected") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ g_object_ref (drive);
+ g_hash_table_remove (monitor->drives, id);
+ signal_emit_in_idle (drive, "disconnected", NULL);
+ signal_emit_in_idle (monitor, "drive-disconnected", drive);
+ g_object_unref (drive);
+ }
+ }
+ else if (strcmp (member, "DriveEjectButton") == 0)
+ {
+ drive = g_hash_table_lookup (monitor->drives, id);
+ if (drive != NULL)
+ {
+ signal_emit_in_idle (drive, "eject-button", NULL);
+ signal_emit_in_idle (monitor, "drive-eject-button", drive);
+ }
+ }
+
+ }
+ else if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeAdded") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeRemoved") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountOpAskPassword") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountOpAskQuestion") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountOpAborted"))
+ {
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "VolumeChanged") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ {
+ GProxyShadowMount *shadow_mount;
+
+ g_proxy_volume_update (volume, &iter);
+ signal_emit_in_idle (volume, "changed", NULL);
+ signal_emit_in_idle (monitor, "volume-changed", volume);
+
+ shadow_mount = g_proxy_volume_get_shadow_mount (volume);
+ if (shadow_mount != NULL)
+ {
+ signal_emit_in_idle (shadow_mount, "changed", NULL);
+ signal_emit_in_idle (monitor, "mount-changed", shadow_mount);
+ g_object_unref (shadow_mount);
+ }
+ }
+ }
+ else if (strcmp (member, "VolumeAdded") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume == NULL)
+ {
+ volume = g_proxy_volume_new (monitor);
+ g_proxy_volume_update (volume, &iter);
+ g_hash_table_insert (monitor->volumes, g_strdup (g_proxy_volume_get_id (volume)), volume);
+ signal_emit_in_idle (monitor, "volume-added", volume);
+ }
+ }
+ else if (strcmp (member, "VolumeRemoved") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ {
+ g_object_ref (volume);
+ g_hash_table_remove (monitor->volumes, id);
+ signal_emit_in_idle (volume, "removed", NULL);
+ signal_emit_in_idle (monitor, "volume-removed", volume);
+ g_object_unref (volume);
+ }
+ }
+ else if (strcmp (member, "MountOpAskPassword") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ g_proxy_volume_handle_mount_op_ask_password (volume, &iter);
+ }
+ else if (strcmp (member, "MountOpAskQuestion") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ g_proxy_volume_handle_mount_op_ask_question (volume, &iter);
+ }
+ else if (strcmp (member, "MountOpAborted") == 0)
+ {
+ volume = g_hash_table_lookup (monitor->volumes, id);
+ if (volume != NULL)
+ g_proxy_volume_handle_mount_op_aborted (volume, &iter);
+ }
+
+ }
+ else if (dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountChanged") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountAdded") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountPreUnmount") ||
+ dbus_message_is_signal (message, "org.gtk.Private.RemoteVolumeMonitor", "MountRemoved"))
+ {
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &the_dbus_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &id);
+ dbus_message_iter_next (&iter);
+
+ if (strcmp (the_dbus_name, klass->dbus_name) != 0)
+ goto not_for_us;
+
+ if (strcmp (member, "MountChanged") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ g_proxy_mount_update (mount, &iter);
+ signal_emit_in_idle (mount, "changed", NULL);
+ signal_emit_in_idle (monitor, "mount-changed", mount);
+ }
+ }
+ else if (strcmp (member, "MountAdded") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount == NULL)
+ {
+ mount = g_proxy_mount_new (monitor);
+ g_proxy_mount_update (mount, &iter);
+ g_hash_table_insert (monitor->mounts, g_strdup (g_proxy_mount_get_id (mount)), mount);
+ signal_emit_in_idle (monitor, "mount-added", mount);
+ }
+ }
+ else if (strcmp (member, "MountPreUnmount") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ signal_emit_in_idle (mount, "pre-unmount", NULL);
+ signal_emit_in_idle (monitor, "mount-pre-unmount", mount);
+ }
+ }
+ else if (strcmp (member, "MountRemoved") == 0)
+ {
+ mount = g_hash_table_lookup (monitor->mounts, id);
+ if (mount != NULL)
+ {
+ g_object_ref (mount);
+ g_hash_table_remove (monitor->mounts, id);
+ signal_emit_in_idle (mount, "unmounted", NULL);
+ signal_emit_in_idle (monitor, "mount-removed", mount);
+ g_object_unref (mount);
+ }
+ }
+ }
+
+ not_for_us:
+ G_UNLOCK (proxy_vm);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+g_proxy_volume_monitor_init (GProxyVolumeMonitor *monitor)
+{
+ g_proxy_volume_monitor_setup_session_bus_connection (TRUE);
+}
+
+static void
+g_proxy_volume_monitor_class_finalize (GProxyVolumeMonitorClass *klass)
+{
+ g_free (klass->dbus_name);
+}
+
+typedef struct {
+ char *dbus_name;
+ gboolean is_native;
+ int is_supported_nr;
+} ProxyClassData;
+
+static ProxyClassData *
+proxy_class_data_new (const char *dbus_name, gboolean is_native)
+{
+ ProxyClassData *data;
+ static int is_supported_nr = 0;
+
+ data = g_new0 (ProxyClassData, 1);
+ data->dbus_name = g_strdup (dbus_name);
+ data->is_native = is_native;
+ data->is_supported_nr = is_supported_nr++;
+
+ g_assert (is_supported_funcs[data->is_supported_nr] != NULL);
+
+ return data;
+}
+
+static void
+g_proxy_volume_monitor_class_intern_init_pre (GProxyVolumeMonitorClass *klass, gconstpointer class_data)
+{
+ ProxyClassData *data = (ProxyClassData *) class_data;
+ klass->dbus_name = g_strdup (data->dbus_name);
+ klass->is_native = data->is_native;
+ klass->is_supported_nr = data->is_supported_nr;
+ g_proxy_volume_monitor_class_intern_init (klass);
+}
+
+static gboolean
+is_remote_monitor_supported (const char *dbus_name)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ dbus_bool_t is_supported;
+
+ message = NULL;
+ reply = NULL;
+ is_supported = FALSE;
+
+ message = dbus_message_new_method_call (dbus_name,
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "IsSupported");
+ if (message == NULL)
+ {
+ g_warning ("Cannot allocate memory for DBusMessage");
+ goto fail;
+ }
+ dbus_error_init (&dbus_error);
+ reply = dbus_connection_send_with_reply_and_block (the_session_bus,
+ message,
+ -1,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("invoking IsSupported() failed for remote volume monitor with dbus name %s: %s: %s",
+ dbus_name,
+ dbus_error.name,
+ dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ if (!dbus_message_get_args (reply, &dbus_error,
+ DBUS_TYPE_BOOLEAN, &is_supported,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args in reply for IsSupported(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ if (!is_supported)
+ g_warning ("remote volume monitor with dbus name %s is not supported", dbus_name);
+
+ fail:
+ if (message != NULL)
+ dbus_message_unref (message);
+ if (reply != NULL)
+ dbus_message_unref (reply);
+ return is_supported;
+}
+
+static gboolean
+is_supported (GProxyVolumeMonitorClass *klass)
+{
+ gboolean res;
+
+ G_LOCK (proxy_vm);
+ res = g_proxy_volume_monitor_setup_session_bus_connection (FALSE);
+ G_UNLOCK (proxy_vm);
+
+ if (res)
+ res = is_remote_monitor_supported (klass->dbus_name);
+
+ return res;
+}
+
+static void
+g_proxy_volume_monitor_class_init (GProxyVolumeMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+ GNativeVolumeMonitorClass *native_class = G_NATIVE_VOLUME_MONITOR_CLASS (klass);
+ int i;
+
+ gobject_class->constructor = g_proxy_volume_monitor_constructor;
+ gobject_class->finalize = g_proxy_volume_monitor_finalize;
+ gobject_class->dispose = g_proxy_volume_monitor_dispose;
+
+ monitor_class->get_mounts = get_mounts;
+ monitor_class->get_volumes = get_volumes;
+ monitor_class->get_connected_drives = get_connected_drives;
+ monitor_class->get_volume_for_uuid = get_volume_for_uuid;
+ monitor_class->get_mount_for_uuid = get_mount_for_uuid;
+
+ i = klass->is_supported_nr;
+ is_supported_classes[i] = klass;
+ monitor_class->is_supported = is_supported_funcs[i];
+
+ native_class->get_mount_for_mount_path = get_mount_for_mount_path;
+}
+
+/* Call with proxy_vm lock held */
+static void
+seed_monitor (GProxyVolumeMonitor *monitor)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ DBusMessageIter iter_reply;
+ DBusMessageIter iter_array;
+
+ message = dbus_message_new_method_call (g_proxy_volume_monitor_get_dbus_name (monitor),
+ "/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "List");
+ if (message == NULL)
+ {
+ g_warning ("Cannot allocate memory for DBusMessage");
+ goto fail;
+ }
+ dbus_error_init (&dbus_error);
+ reply = dbus_connection_send_with_reply_and_block (monitor->session_bus,
+ message,
+ -1,
+ &dbus_error);
+ dbus_message_unref (message);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("invoking List() failed for type %s: %s: %s",
+ G_OBJECT_TYPE_NAME (monitor),
+ dbus_error.name,
+ dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto fail;
+ }
+
+ dbus_message_iter_init (reply, &iter_reply);
+
+ /* TODO: verify signature */
+
+ /* drives */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyDrive *drive;
+ const char *id;
+ drive = g_proxy_drive_new (monitor);
+ g_proxy_drive_update (drive, &iter_array);
+ id = g_proxy_drive_get_id (drive);
+ g_hash_table_insert (monitor->drives, g_strdup (id), drive);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ /* volumes */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyVolume *volume;
+ const char *id;
+ volume = g_proxy_volume_new (monitor);
+ g_proxy_volume_update (volume, &iter_array);
+ id = g_proxy_volume_get_id (volume);
+ g_hash_table_insert (monitor->volumes, g_strdup (id), volume);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ /* mounts */
+ dbus_message_iter_recurse (&iter_reply, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ GProxyMount *mount;
+ const char *id;
+ mount = g_proxy_mount_new (monitor);
+ g_proxy_mount_update (mount, &iter_array);
+ id = g_proxy_mount_get_id (mount);
+ g_hash_table_insert (monitor->mounts, g_strdup (id), mount);
+ dbus_message_iter_next (&iter_array);
+ }
+ dbus_message_iter_next (&iter_reply);
+
+ monitor->unique_name = g_strdup (dbus_message_get_sender (reply));
+
+ dbus_message_unref (reply);
+
+ fail:
+ ;
+}
+
+GProxyDrive *
+g_proxy_volume_monitor_get_drive_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyDrive *drive;
+
+ G_LOCK (proxy_vm);
+ drive = g_hash_table_lookup (volume_monitor->drives, id);
+ if (drive != NULL)
+ g_object_ref (drive);
+ G_UNLOCK (proxy_vm);
+
+ return drive;
+}
+
+GProxyVolume *
+g_proxy_volume_monitor_get_volume_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyVolume *volume;
+
+ G_LOCK (proxy_vm);
+ volume = g_hash_table_lookup (volume_monitor->volumes, id);
+ if (volume != NULL)
+ g_object_ref (volume);
+ G_UNLOCK (proxy_vm);
+
+ return volume;
+}
+
+GProxyMount *
+g_proxy_volume_monitor_get_mount_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id)
+{
+ GProxyMount *mount;
+
+ G_LOCK (proxy_vm);
+ mount = g_hash_table_lookup (volume_monitor->mounts, id);
+ if (mount != NULL)
+ g_object_ref (mount);
+ G_UNLOCK (proxy_vm);
+
+ return mount;
+}
+
+
+GHashTable *
+_get_identifiers (DBusMessageIter *iter)
+{
+ GHashTable *hash_table;
+ DBusMessageIter iter_array;
+
+ hash_table = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_free);
+
+ dbus_message_iter_recurse (iter, &iter_array);
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ DBusMessageIter iter_dict_entry;
+ const char *key;
+ const char *value;
+
+ dbus_message_iter_recurse (&iter_array, &iter_dict_entry);
+ dbus_message_iter_get_basic (&iter_dict_entry, &key);
+ dbus_message_iter_next (&iter_dict_entry);
+ dbus_message_iter_get_basic (&iter_dict_entry, &value);
+
+ g_hash_table_insert (hash_table, g_strdup (key), g_strdup (value));
+
+ dbus_message_iter_next (&iter_array);
+ }
+
+ return hash_table;
+}
+
+DBusConnection *
+g_proxy_volume_monitor_get_dbus_connection (GProxyVolumeMonitor *volume_monitor)
+{
+ return dbus_connection_ref (volume_monitor->session_bus);
+}
+
+const char *
+g_proxy_volume_monitor_get_dbus_name (GProxyVolumeMonitor *volume_monitor)
+{
+ GProxyVolumeMonitorClass *klass = G_PROXY_VOLUME_MONITOR_CLASS (G_OBJECT_GET_CLASS (volume_monitor));
+ return klass->dbus_name;
+}
+
+static void
+register_volume_monitor (GTypeModule *type_module,
+ const char *type_name,
+ const char *dbus_name,
+ gboolean is_native,
+ int priority)
+{
+ GType type;
+ const GTypeInfo type_info = {
+ sizeof (GProxyVolumeMonitorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) g_proxy_volume_monitor_class_intern_init_pre,
+ (GClassFinalizeFunc) g_proxy_volume_monitor_class_finalize,
+ (gconstpointer) proxy_class_data_new (dbus_name, is_native), /* class_data (leaked!) */
+ sizeof (GProxyVolumeMonitor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) g_proxy_volume_monitor_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_module_register_type (type_module,
+ G_TYPE_PROXY_VOLUME_MONITOR,
+ type_name,
+ &type_info,
+ 0 /* type_flags */);
+
+ g_io_extension_point_implement (is_native ? G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME :
+ G_VOLUME_MONITOR_EXTENSION_POINT_NAME,
+ type,
+ type_name,
+ priority);
+}
+
+/* Call with proxy_vm lock held */
+gboolean
+g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration)
+{
+ gboolean ret;
+ DBusError dbus_error;
+
+ ret = FALSE;
+
+ if (the_session_bus != NULL)
+ goto has_bus_already;
+
+ /* This is so that system daemons can use gio
+ * without spawning private dbus instances.
+ * See bug 526454.
+ */
+ if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
+ goto out;
+
+ dbus_error_init (&dbus_error);
+ the_session_bus = dbus_bus_get_private (DBUS_BUS_SESSION, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("cannot connect to the session bus: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ the_volume_monitors = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ has_bus_already:
+
+ if (need_integration && !the_session_bus_is_integrated)
+ {
+ _g_dbus_connection_integrate_with_main (the_session_bus);
+ the_session_bus_is_integrated = TRUE;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+void
+g_proxy_volume_monitor_teardown_session_bus_connection (void)
+{
+ G_LOCK (proxy_vm);
+ if (the_session_bus != NULL)
+ {
+ if (the_session_bus_is_integrated)
+ _g_dbus_connection_remove_from_main (the_session_bus);
+ the_session_bus_is_integrated = FALSE;
+ dbus_connection_close (the_session_bus);
+ the_session_bus = NULL;
+
+ g_hash_table_unref (the_volume_monitors);
+ the_volume_monitors = NULL;
+ }
+ G_UNLOCK (proxy_vm);
+}
+
+void
+g_proxy_volume_monitor_register (GIOModule *module)
+{
+ GDir *dir;
+ GError *error;
+
+ /* first register the abstract base type... */
+ g_proxy_volume_monitor_register_type (G_TYPE_MODULE (module));
+
+ /* ... then register instantiable types for each remote volume
+ * monitor - each remote volume monitor is defined in a key-value
+ * file in $(datadir)/gvfs/remote-volume-monitors that must have
+ * the suffix .monitor. Each file specifies
+ *
+ * - the name of the volume monitor
+ * - the name of the D-Bus service
+ * - whether the volume monitor is native
+ * - and if so the priority
+ */
+
+ error = NULL;
+ dir = g_dir_open (REMOTE_VOLUME_MONITORS_DIR, 0, &error);
+ if (dir == NULL)
+ {
+ g_warning ("cannot open directory " REMOTE_VOLUME_MONITORS_DIR ": %s", error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ const char *name;
+
+ while ((name = g_dir_read_name (dir)) != NULL)
+ {
+ GKeyFile *key_file;
+ char *type_name;
+ char *path;
+ char *dbus_name;
+ gboolean is_native;
+ int native_priority;
+
+ type_name = NULL;
+ key_file = NULL;
+ dbus_name = NULL;
+ path = NULL;
+
+ if (!g_str_has_suffix (name, ".monitor"))
+ goto cont;
+
+ path = g_build_filename (REMOTE_VOLUME_MONITORS_DIR, name, NULL);
+
+ key_file = g_key_file_new ();
+ error = NULL;
+ if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
+ {
+ g_warning ("error loading key-value file %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ type_name = g_key_file_get_string (key_file, "RemoteVolumeMonitor", "Name", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting Name key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ dbus_name = g_key_file_get_string (key_file, "RemoteVolumeMonitor", "DBusName", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting DBusName key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ is_native = g_key_file_get_boolean (key_file, "RemoteVolumeMonitor", "IsNative", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting IsNative key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+
+ if (is_native)
+ {
+ native_priority = g_key_file_get_integer (key_file, "RemoteVolumeMonitor", "NativePriority", &error);
+ if (error != NULL)
+ {
+ g_warning ("error extracting NativePriority key from %s: %s", path, error->message);
+ g_error_free (error);
+ goto cont;
+ }
+ }
+ else
+ {
+ native_priority = 0;
+ }
+
+ register_volume_monitor (G_TYPE_MODULE (module),
+ type_name,
+ dbus_name,
+ is_native,
+ native_priority);
+
+ cont:
+
+ g_free (type_name);
+ g_free (dbus_name);
+ g_free (path);
+ if (key_file != NULL)
+ g_key_file_free (key_file);
+ }
+ g_dir_close (dir);
+ }
+}
diff --git a/trunk/monitor/proxy/gproxyvolumemonitor.h b/trunk/monitor/proxy/gproxyvolumemonitor.h
new file mode 100644
index 00000000..96b9d841
--- /dev/null
+++ b/trunk/monitor/proxy/gproxyvolumemonitor.h
@@ -0,0 +1,77 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_PROXY_VOLUME_MONITOR_H__
+#define __G_PROXY_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PROXY_VOLUME_MONITOR (g_proxy_volume_monitor_get_type ())
+#define G_PROXY_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_PROXY_VOLUME_MONITOR, GProxyVolumeMonitor))
+#define G_PROXY_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_PROXY_VOLUME_MONITOR, GProxyVolumeMonitorClass))
+#define G_PROXY_VOLUME_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_PROXY_VOLUME_MONITOR, GProxyVolumeMonitorClass))
+#define G_IS_PROXY_VOLUME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_PROXY_VOLUME_MONITOR))
+#define G_IS_PROXY_VOLUME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_PROXY_VOLUME_MONITOR))
+
+typedef struct _GProxyVolumeMonitor GProxyVolumeMonitor;
+typedef struct _GProxyVolumeMonitorClass GProxyVolumeMonitorClass;
+
+/* Forward definitions */
+typedef struct _GProxyDrive GProxyDrive;
+typedef struct _GProxyVolume GProxyVolume;
+typedef struct _GProxyMount GProxyMount;
+typedef struct _GProxyShadowMount GProxyShadowMount;
+
+struct _GProxyVolumeMonitorClass {
+ GNativeVolumeMonitorClass parent_class;
+ char *dbus_name;
+ gboolean is_native;
+ int is_supported_nr;
+};
+
+GType g_proxy_volume_monitor_get_type (void) G_GNUC_CONST;
+
+void g_proxy_volume_monitor_register (GIOModule *module);
+GProxyDrive *g_proxy_volume_monitor_get_drive_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+GProxyVolume *g_proxy_volume_monitor_get_volume_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+GProxyMount *g_proxy_volume_monitor_get_mount_for_id (GProxyVolumeMonitor *volume_monitor,
+ const char *id);
+DBusConnection *g_proxy_volume_monitor_get_dbus_connection (GProxyVolumeMonitor *volume_monitor);
+const char *g_proxy_volume_monitor_get_dbus_name (GProxyVolumeMonitor *volume_monitor);
+
+gboolean g_proxy_volume_monitor_setup_session_bus_connection (gboolean need_integration);
+void g_proxy_volume_monitor_teardown_session_bus_connection (void);
+
+
+GHashTable *_get_identifiers (DBusMessageIter *iter);
+
+G_END_DECLS
+
+#endif /* __G_PROXY_VOLUME_MONITOR_H__ */
diff --git a/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.c b/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.c
new file mode 100644
index 00000000..e59374db
--- /dev/null
+++ b/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.c
@@ -0,0 +1,1755 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <locale.h>
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <glib/gprintf.h>
+
+#include "gdbusutils.h"
+#include "gvfsproxyvolumemonitordaemon.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* #define DEBUG_ENABLED */
+
+#ifdef DEBUG_ENABLED
+static void
+print_debug (const gchar *format, ...)
+{
+ va_list var_args;
+
+ va_start (var_args, format);
+
+ g_print ("### debug: ");
+ g_vprintf (format, var_args);
+ g_print ("\n");
+
+ va_end (var_args);
+}
+#else
+static void
+print_debug (const gchar *format, ...)
+{
+}
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+GType g_proxy_mount_operation_get_type (void) G_GNUC_CONST;
+
+typedef struct
+{
+ GMountOperation parent_instance;
+} GProxyMountOperation;
+
+typedef struct
+{
+ GMountOperationClass parent_class;
+} GProxyMountOperationClass;
+
+
+static GMountOperation *
+g_proxy_mount_operation_new (void)
+{
+ return G_MOUNT_OPERATION (g_object_new (g_proxy_mount_operation_get_type(), NULL));
+}
+
+G_DEFINE_TYPE (GProxyMountOperation, g_proxy_mount_operation, G_TYPE_MOUNT_OPERATION)
+
+static void
+g_proxy_mount_operation_init (GProxyMountOperation *mount_operation)
+{
+}
+
+static void
+g_proxy_mount_operation_ask_password (GMountOperation *op,
+ const char *message,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags)
+{
+ /* do nothing */
+}
+
+static void
+g_proxy_mount_operation_ask_question (GMountOperation *op,
+ const char *message,
+ const char *choices[])
+{
+ /* do nothing */
+}
+
+static void
+g_proxy_mount_operation_class_init (GProxyMountOperationClass *klass)
+{
+ GMountOperationClass *mount_op_class;
+
+ mount_op_class = G_MOUNT_OPERATION_CLASS (klass);
+
+ mount_op_class->ask_password = g_proxy_mount_operation_ask_password;
+ mount_op_class->ask_question = g_proxy_mount_operation_ask_question;
+}
+
+
+static GVolumeMonitor *monitor = NULL;
+static DBusConnection *connection = NULL;
+static GType the_volume_monitor_type;
+static const char *the_dbus_name = NULL;
+
+static GList *outstanding_ops = NULL;
+
+static GHashTable *unique_names_being_watched = NULL;
+
+static void
+cancellable_destroyed_cb (gpointer user_data,
+ GObject *where_the_cancellable_was)
+{
+ outstanding_ops = g_list_remove (outstanding_ops, where_the_cancellable_was);
+}
+
+static void
+remove_name_owned_changed_for_unique_name (const gchar *unique_name)
+{
+ const gchar *match_rule;
+ DBusError dbus_error;
+
+ match_rule = g_hash_table_lookup (unique_names_being_watched, unique_name);
+ if (match_rule == NULL)
+ {
+ g_warning ("Was asked to remove match rule for unique_name %s but we don't have one", unique_name);
+ goto out;
+ }
+
+ dbus_error_init (&dbus_error);
+ dbus_bus_remove_match (connection,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("cannot remove match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ }
+
+ g_hash_table_remove (unique_names_being_watched, unique_name);
+
+ out:
+ ;
+}
+
+static void
+ensure_name_owner_changed_for_unique_name (const gchar *unique_name)
+{
+ gchar *match_rule;
+ DBusError dbus_error;
+
+ if (g_hash_table_lookup (unique_names_being_watched, unique_name) != NULL)
+ goto out;
+
+ match_rule = g_strdup_printf ("type='signal',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',"
+ "arg0='%s'",
+ unique_name);
+
+ dbus_error_init (&dbus_error);
+ dbus_bus_add_match (connection,
+ match_rule,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("cannot add match rule '%s': %s: %s", match_rule, dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ g_free (match_rule);
+ goto out;
+ }
+
+ g_hash_table_insert (unique_names_being_watched, g_strdup (unique_name), match_rule);
+
+ out:
+ ;
+}
+
+static void monitor_try_create (void);
+
+/* string id
+ * string name
+ * string gicon_data
+ * boolean can-eject
+ * boolean can-poll-for-media
+ * boolean has-media
+ * boolean is-media-removable
+ * boolean is-media-check-automatic
+ * array:string volume-ids
+ * dict:string->string identifiers
+ */
+#define DRIVE_STRUCT_TYPE "(sssbbbbbasa{ss})"
+
+static void
+append_drive (GDrive *drive, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_volume_array;
+ DBusMessageIter iter_identifiers;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ gboolean can_eject;
+ gboolean can_poll_for_media;
+ gboolean has_media;
+ gboolean is_media_removable;
+ gboolean is_media_check_automatic;
+ GList *volumes, *l;
+ char **identifiers;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", drive);
+ name = g_drive_get_name (drive);
+ icon = g_drive_get_icon (drive);
+ if (icon)
+ icon_data = g_icon_to_string (icon);
+ else
+ icon_data = g_strdup ("");
+ can_eject = g_drive_can_eject (drive);
+ can_poll_for_media = g_drive_can_poll_for_media (drive);
+ has_media = g_drive_has_media (drive);
+ is_media_removable = g_drive_is_media_removable (drive);
+ is_media_check_automatic = g_drive_is_media_check_automatic (drive);
+ volumes = g_drive_get_volumes (drive);
+ identifiers = g_drive_enumerate_identifiers (drive);
+
+ if (name == NULL)
+ name = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_eject);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_poll_for_media);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &has_media);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &is_media_removable);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &is_media_check_automatic);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_volume_array);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ GVolume *volume = G_VOLUME (l->data);
+ char *volume_id;
+ volume_id = g_strdup_printf ("%p", volume);
+ dbus_message_iter_append_basic (&iter_volume_array, DBUS_TYPE_STRING, &volume_id);
+ g_free (volume_id);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_volume_array);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}", &iter_identifiers);
+ for (n = 0; identifiers != NULL && identifiers[n] != NULL; n++)
+ {
+ DBusMessageIter iter_dict_entry;
+ char *id_value;
+ id_value = g_drive_get_identifier (drive, identifiers[n]);
+ dbus_message_iter_open_container (&iter_identifiers,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &iter_dict_entry);
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &(identifiers[n]));
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &id_value);
+ dbus_message_iter_close_container (&iter_identifiers, &iter_dict_entry);
+ g_free (id_value);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_identifiers);
+
+ g_strfreev (identifiers);
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string activation_uri
+ * boolean can-mount
+ * boolean should-automount
+ * string drive-id
+ * string mount-id
+ * dict:string->string identifiers
+ */
+#define VOLUME_STRUCT_TYPE "(sssssbbssa{ss})"
+
+static void
+append_volume (GVolume *volume, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_identifiers;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ char *uuid;
+ GFile *activation_root;
+ char *activation_uri;
+ gboolean can_mount;
+ gboolean should_automount;
+ GDrive *drive;
+ char *drive_id;
+ GMount *mount;
+ char *mount_id;
+ char **identifiers;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", volume);
+ name = g_volume_get_name (volume);
+ icon = g_volume_get_icon (volume);
+ if (icon)
+ icon_data = g_icon_to_string (icon);
+ else
+ icon_data = g_strdup ("");
+ uuid = g_volume_get_uuid (volume);
+ activation_root = g_volume_get_activation_root (volume);
+ if (activation_root == NULL)
+ activation_uri = g_strdup ("");
+ else
+ activation_uri = g_file_get_uri (activation_root);
+ can_mount = g_volume_can_mount (volume);
+ should_automount = g_volume_should_automount (volume);
+ drive = g_volume_get_drive (volume);
+ if (drive == NULL)
+ drive_id = g_strdup ("");
+ else
+ drive_id = g_strdup_printf ("%p", drive);
+ mount = g_volume_get_mount (volume);
+ if (mount == NULL)
+ mount_id = g_strdup ("");
+ else
+ mount_id = g_strdup_printf ("%p", mount);
+ identifiers = g_volume_enumerate_identifiers (volume);
+
+ if (name == NULL)
+ name = g_strdup ("");
+ if (uuid == NULL)
+ uuid = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &activation_uri);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_mount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &should_automount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &drive_id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &mount_id);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}", &iter_identifiers);
+ for (n = 0; identifiers != NULL && identifiers[n] != NULL; n++)
+ {
+ DBusMessageIter iter_dict_entry;
+ char *id_value;
+ id_value = g_volume_get_identifier (volume, identifiers[n]);
+ dbus_message_iter_open_container (&iter_identifiers,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &iter_dict_entry);
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &(identifiers[n]));
+ dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &id_value);
+ dbus_message_iter_close_container (&iter_identifiers, &iter_dict_entry);
+ g_free (id_value);
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_identifiers);
+
+ g_strfreev (identifiers);
+ g_free (mount_id);
+ if (mount != NULL)
+ g_object_unref (mount);
+ g_free (drive_id);
+ if (drive != NULL)
+ g_object_unref (drive);
+ g_free (uuid);
+ if (activation_root != NULL)
+ g_object_unref (activation_root);
+ g_free (activation_uri);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+/* string id
+ * string name
+ * string gicon_data
+ * string uuid
+ * string root_uri
+ * boolean can-unmount
+ * string volume-id
+ * array:string x-content-types
+ */
+#define MOUNT_STRUCT_TYPE "(sssssbsas)"
+
+static void
+append_mount (GMount *mount, DBusMessageIter *iter_array)
+{
+ DBusMessageIter iter_struct;
+ DBusMessageIter iter_x_content_types_array;
+ char *id;
+ char *name;
+ GIcon *icon;
+ char *icon_data;
+ char *uuid;
+ GFile *root;
+ char *root_uri;
+ gboolean can_unmount;
+ GVolume *volume;
+ char *volume_id;
+ char **x_content_types;
+ int n;
+
+ dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
+
+ id = g_strdup_printf ("%p", mount);
+ name = g_mount_get_name (mount);
+ icon = g_mount_get_icon (mount);
+ if (icon)
+ icon_data = g_icon_to_string (icon);
+ else
+ icon_data = g_strdup ("");
+ uuid = g_mount_get_uuid (mount);
+ root = g_mount_get_root (mount);
+ root_uri = g_file_get_uri (root);
+ can_unmount = g_mount_can_unmount (mount);
+ volume = g_mount_get_volume (mount);
+ if (volume == NULL)
+ volume_id = g_strdup ("");
+ else
+ volume_id = g_strdup_printf ("%p", volume);
+
+ if (name == NULL)
+ name = g_strdup ("");
+ if (uuid == NULL)
+ uuid = g_strdup ("");
+
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &icon_data);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &root_uri);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &can_unmount);
+ dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &volume_id);
+
+ dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", &iter_x_content_types_array);
+ x_content_types = (char **) g_object_get_data (G_OBJECT (mount), "x-content-types");
+ if (x_content_types != NULL)
+ {
+ for (n = 0; x_content_types[n] != NULL; n++)
+ dbus_message_iter_append_basic (&iter_x_content_types_array, DBUS_TYPE_STRING, &(x_content_types[n]));
+ }
+ dbus_message_iter_close_container (&iter_struct, &iter_x_content_types_array);
+
+ g_free (volume_id);
+ if (volume != NULL)
+ g_object_unref (volume);
+ g_free (root_uri);
+ g_object_unref (root);
+ g_free (uuid);
+ g_free (icon_data);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (id);
+
+ dbus_message_iter_close_container (iter_array, &iter_struct);
+}
+
+static DBusHandlerResult
+handle_list (DBusConnection *connection, DBusMessage *message)
+{
+ GList *drives;
+ GList *volumes;
+ GList *mounts;
+ DBusMessageIter iter;
+ DBusMessageIter iter_array;
+ DBusMessage *reply;
+
+ print_debug ("in handle_list");
+
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ volumes = g_volume_monitor_get_volumes (monitor);
+ mounts = g_volume_monitor_get_mounts (monitor);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_message_iter_init_append (reply, &iter);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DRIVE_STRUCT_TYPE, &iter_array);
+ g_list_foreach (drives, (GFunc) append_drive, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, VOLUME_STRUCT_TYPE, &iter_array);
+ g_list_foreach (volumes, (GFunc) append_volume, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, MOUNT_STRUCT_TYPE, &iter_array);
+ g_list_foreach (mounts, (GFunc) append_mount, &iter_array);
+ dbus_message_iter_close_container (&iter, &iter_array);
+
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+mount_unmount_cb (GMount *mount, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ print_debug ("in mount_unmount_cb");
+
+ g_object_set_data (G_OBJECT (mount), "cancellable", NULL);
+
+ error = NULL;
+ if (!g_mount_unmount_finish (mount, result, &error))
+ {
+ print_debug (" error: %s", error->message);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ print_debug (" success");
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_mount_unmount (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ const char *cancellation_id;
+ const char *sender;
+ GCancellable *cancellable;
+ dbus_uint32_t unmount_flags;
+ DBusError dbus_error;
+ GList *mounts, *l;
+ GMount *mount;
+ DBusHandlerResult ret;
+
+ mounts = NULL;
+ unmount_flags = 0;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_STRING, &cancellation_id,
+ DBUS_TYPE_UINT32, &unmount_flags,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for MountUnmount(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_mount_unmount");
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ sender = dbus_message_get_sender (message);
+
+ mount = NULL;
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ char *mount_id;
+
+ mount = G_MOUNT (l->data);
+ mount_id = g_strdup_printf ("%p", mount);
+ if (strcmp (mount_id, id) == 0)
+ break;
+
+ g_free (mount_id);
+ }
+ if (l == NULL)
+ mount = NULL;
+
+ if (mount == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given mount was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ if (g_object_get_data (G_OBJECT (mount), "cancellable") != NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.Failed",
+ "An operation is already pending");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ cancellable = g_cancellable_new ();
+ g_object_set_data_full (G_OBJECT (mount), "cancellable", cancellable, g_object_unref);
+ g_object_set_data_full (G_OBJECT (cancellable), "owner", g_strdup (sender), g_free);
+ g_object_set_data_full (G_OBJECT (cancellable), "cancellation_id", g_strdup (cancellation_id), g_free);
+ outstanding_ops = g_list_prepend (outstanding_ops, cancellable);
+ g_object_weak_ref (G_OBJECT (cancellable),
+ cancellable_destroyed_cb,
+ NULL);
+
+ g_mount_unmount (mount,
+ unmount_flags,
+ NULL,
+ (GAsyncReadyCallback) mount_unmount_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (mounts != NULL)
+ {
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+handle_mount_op_reply (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ const char *mount_op_id;
+ dbus_int32_t result;
+ const char *user_name;
+ const char *domain;
+ const char *encoded_password;
+ char *decoded_password;
+ gsize decoded_password_len;
+ dbus_int32_t password_save;
+ dbus_int32_t choice;
+ dbus_bool_t anonymous;
+ DBusError dbus_error;
+ DBusHandlerResult ret;
+ GList *volumes, *l;
+ GVolume *volume;
+ DBusMessage *reply;
+ GMountOperation *mount_operation;
+
+ volumes = NULL;
+ decoded_password = NULL;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_STRING, &mount_op_id,
+ DBUS_TYPE_INT32, &result,
+ DBUS_TYPE_STRING, &user_name,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_STRING, &encoded_password,
+ DBUS_TYPE_INT32, &password_save,
+ DBUS_TYPE_INT32, &choice,
+ DBUS_TYPE_BOOLEAN, &anonymous,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for MountOpReply(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_mount_op_reply");
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ volume = NULL;
+ volumes = g_volume_monitor_get_volumes (monitor);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ char *volume_id;
+
+ volume = G_VOLUME (l->data);
+ volume_id = g_strdup_printf ("%p", volume);
+ if (strcmp (volume_id, id) == 0)
+ break;
+
+ g_free (volume_id);
+ }
+ if (l == NULL)
+ volume = NULL;
+
+ if (volume == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given volume was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ mount_operation = g_object_get_data (G_OBJECT (volume), "mount_operation");
+ if (mount_operation == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "No outstanding mount operation");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ decoded_password = (gchar *) g_base64_decode (encoded_password, &decoded_password_len);
+
+ g_mount_operation_set_username (mount_operation, user_name);
+ g_mount_operation_set_domain (mount_operation, domain);
+ g_mount_operation_set_password (mount_operation, decoded_password);
+ g_mount_operation_set_password_save (mount_operation, password_save);
+ g_mount_operation_set_choice (mount_operation, choice);
+ g_mount_operation_set_anonymous (mount_operation, anonymous);
+
+ g_mount_operation_reply (mount_operation, result);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ out:
+ g_free (decoded_password);
+ if (volumes != NULL)
+ {
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+volume_mount_cb (GVolume *volume, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ print_debug ("in volume_mount_cb");
+
+ g_object_set_data (G_OBJECT (volume), "mount_operation", NULL);
+ g_object_set_data (G_OBJECT (volume), "cancellable", NULL);
+
+ error = NULL;
+ if (!g_volume_mount_finish (volume, result, &error))
+ {
+ print_debug (" error: %s", error->message);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ print_debug (" success");
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static void
+ask_password_cb (GMountOperation *mount_operation,
+ const gchar *message_to_show,
+ const gchar *default_user,
+ const gchar *default_domain,
+ GAskPasswordFlags flags,
+ gpointer user_data)
+{
+ gchar *id;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ GVolume *volume;
+ const gchar *mount_op_id;
+ const gchar *mount_op_owner;
+
+ print_debug ("in ask_password_cb %s", message_to_show);
+
+ volume = G_VOLUME (user_data);
+
+ id = g_strdup_printf ("%p", volume);
+
+ mount_op_id = g_object_get_data (G_OBJECT (mount_operation), "mount_op_id");
+ mount_op_owner = g_object_get_data (G_OBJECT (mount_operation), "mount_op_owner");
+
+ message = dbus_message_new_signal ("/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountOpAskPassword");
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &the_dbus_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &mount_op_id);
+
+ if (message_to_show == NULL)
+ message_to_show = "";
+
+ if (default_user == NULL)
+ default_user = "";
+
+ if (default_domain == NULL)
+ default_domain = "";
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &message_to_show);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &default_user);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &default_domain);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &flags);
+
+ dbus_message_set_destination (message, mount_op_owner);
+
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+
+ g_free (id);
+}
+
+static void
+ask_question_cb (GMountOperation *mount_operation,
+ const gchar *message_to_show,
+ gchar **choices,
+ gpointer user_data)
+{
+ gchar *id;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ DBusMessageIter iter_string_array;
+ const gchar *mount_op_id;
+ const gchar *mount_op_owner;
+ GVolume *volume;
+ guint n;
+
+ print_debug ("in ask_question_cb %s", message_to_show);
+
+ volume = G_VOLUME (user_data);
+
+ id = g_strdup_printf ("%p", volume);
+
+ mount_op_id = g_object_get_data (G_OBJECT (mount_operation), "mount_op_id");
+ mount_op_owner = g_object_get_data (G_OBJECT (mount_operation), "mount_op_owner");
+
+ message = dbus_message_new_signal ("/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountOpAskQuestion");
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &the_dbus_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &mount_op_id);
+
+ if (message_to_show == NULL)
+ message_to_show = "";
+
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &message_to_show);
+
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &iter_string_array);
+ for (n = 0; choices != NULL && choices[n] != NULL; n++)
+ dbus_message_iter_append_basic (&iter_string_array, DBUS_TYPE_STRING, &(choices[n]));
+ dbus_message_iter_close_container (&iter, &iter_string_array);
+
+ dbus_message_set_destination (message, mount_op_owner);
+
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+
+ g_free (id);
+}
+
+static void
+aborted_cb (GMountOperation *mount_operation,
+ gpointer user_data)
+{
+ gchar *id;
+ DBusMessage *message;
+ DBusMessageIter iter;
+ GVolume *volume;
+ const gchar *mount_op_id;
+ const gchar *mount_op_owner;
+
+ print_debug ("in aborted_cb");
+
+ volume = G_VOLUME (user_data);
+
+ id = g_strdup_printf ("%p", volume);
+
+ mount_op_id = g_object_get_data (G_OBJECT (mount_operation), "mount_op_id");
+ mount_op_owner = g_object_get_data (G_OBJECT (mount_operation), "mount_op_owner");
+
+ message = dbus_message_new_signal ("/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ "MountOpAborted");
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &the_dbus_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &mount_op_id);
+
+ dbus_message_set_destination (message, mount_op_owner);
+
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+
+ g_free (id);
+}
+
+static DBusHandlerResult
+handle_volume_mount (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ const char *cancellation_id;
+ const char *sender;
+ dbus_uint32_t mount_flags;
+ const char *mount_op_id;
+ DBusError dbus_error;
+ GList *volumes, *l;
+ GVolume *volume;
+ DBusHandlerResult ret;
+ GMountOperation *mount_operation;
+ GCancellable *cancellable;
+
+ volumes = NULL;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_STRING, &cancellation_id,
+ DBUS_TYPE_UINT32, &mount_flags,
+ DBUS_TYPE_STRING, &mount_op_id,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for VolumeMount(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_volume_mount");
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ sender = dbus_message_get_sender (message);
+
+ volume = NULL;
+ volumes = g_volume_monitor_get_volumes (monitor);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ char *volume_id;
+
+ volume = G_VOLUME (l->data);
+ volume_id = g_strdup_printf ("%p", volume);
+ if (strcmp (volume_id, id) == 0)
+ break;
+
+ g_free (volume_id);
+ }
+ if (l == NULL)
+ volume = NULL;
+
+ if (volume == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given volume was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ if (g_object_get_data (G_OBJECT (volume), "cancellable") != NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.Failed",
+ "An operation is already pending");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ mount_operation = NULL;
+ if (mount_op_id != NULL && strlen (mount_op_id) > 0)
+ {
+ mount_operation = g_proxy_mount_operation_new ();
+ g_signal_connect (mount_operation, "ask-password", G_CALLBACK (ask_password_cb), volume);
+ g_signal_connect (mount_operation, "ask-question", G_CALLBACK (ask_question_cb), volume);
+ g_signal_connect (mount_operation, "aborted", G_CALLBACK (aborted_cb), volume);
+ g_object_set_data_full (G_OBJECT (mount_operation), "mount_op_id", g_strdup (mount_op_id), g_free);
+ g_object_set_data_full (G_OBJECT (mount_operation), "mount_op_owner", g_strdup (sender), g_free);
+ g_object_set_data_full (G_OBJECT (volume), "mount_operation", mount_operation, g_object_unref);
+ }
+
+ cancellable = g_cancellable_new ();
+ g_object_set_data_full (G_OBJECT (volume), "cancellable", cancellable, g_object_unref);
+ g_object_set_data_full (G_OBJECT (cancellable), "owner", g_strdup (sender), g_free);
+ g_object_set_data_full (G_OBJECT (cancellable), "cancellation_id", g_strdup (cancellation_id), g_free);
+ outstanding_ops = g_list_prepend (outstanding_ops, cancellable);
+ g_object_weak_ref (G_OBJECT (cancellable),
+ cancellable_destroyed_cb,
+ NULL);
+
+ g_volume_mount (volume,
+ mount_flags,
+ mount_operation,
+ cancellable,
+ (GAsyncReadyCallback) volume_mount_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (volumes != NULL)
+ {
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+drive_eject_cb (GDrive *drive, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ print_debug ("in drive_eject_cb");
+
+ g_object_set_data (G_OBJECT (drive), "cancellable", NULL);
+
+ error = NULL;
+ if (!g_drive_eject_finish (drive, result, &error))
+ {
+ print_debug (" error: %s", error->message);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ print_debug (" success");
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_drive_eject (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ const char *cancellation_id;
+ const char *sender;
+ GCancellable *cancellable;
+ dbus_uint32_t unmount_flags;
+ DBusError dbus_error;
+ GList *drives, *l;
+ GDrive *drive;
+ DBusHandlerResult ret;
+
+ drive = NULL;
+ drives = NULL;
+ unmount_flags = 0;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_STRING, &cancellation_id,
+ DBUS_TYPE_UINT32 &unmount_flags,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for DriveEject(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_drive_eject");
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ sender = dbus_message_get_sender (message);
+
+ drive = NULL;
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ for (l = drives; l != NULL; l = l->next)
+ {
+ char *drive_id;
+
+ drive = G_DRIVE (l->data);
+ drive_id = g_strdup_printf ("%p", drive);
+ if (strcmp (drive_id, id) == 0)
+ break;
+
+ g_free (drive_id);
+ }
+ if (l == NULL)
+ drive = NULL;
+
+ if (drive == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given drive was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ if (g_object_get_data (G_OBJECT (drive), "cancellable") != NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.Failed",
+ "An operation is already pending");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ cancellable = g_cancellable_new ();
+ g_object_set_data_full (G_OBJECT (drive), "cancellable", cancellable, g_object_unref);
+ g_object_set_data_full (G_OBJECT (cancellable), "owner", g_strdup (sender), g_free);
+ g_object_set_data_full (G_OBJECT (cancellable), "cancellation_id", g_strdup (cancellation_id), g_free);
+ outstanding_ops = g_list_prepend (outstanding_ops, cancellable);
+ g_object_weak_ref (G_OBJECT (cancellable),
+ cancellable_destroyed_cb,
+ NULL);
+
+ g_drive_eject (drive,
+ unmount_flags,
+ cancellable,
+ (GAsyncReadyCallback) drive_eject_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (drives != NULL)
+ {
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+drive_poll_for_media_cb (GDrive *drive, GAsyncResult *result, DBusMessage *message)
+{
+ GError *error;
+ DBusMessage *reply;
+
+ print_debug ("in drive_poll_for_media_cb");
+
+ g_object_set_data (G_OBJECT (drive), "cancellable", NULL);
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (drive, result, &error))
+ {
+ print_debug (" error: %s", error->message);
+ reply = _dbus_message_new_from_gerror (message, error);
+ g_error_free (error);
+ }
+ else
+ {
+ print_debug (" success");
+ reply = dbus_message_new_method_return (message);
+ }
+
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+}
+
+static DBusHandlerResult
+handle_drive_poll_for_media (DBusConnection *connection, DBusMessage *message)
+{
+ const char *id;
+ const char *cancellation_id;
+ const char *sender;
+ GCancellable *cancellable;
+ DBusError dbus_error;
+ GList *drives, *l;
+ GDrive *drive;
+ DBusHandlerResult ret;
+
+ drive = NULL;
+ drives = NULL;
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &id,
+ DBUS_TYPE_STRING, &cancellation_id,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for DrivePollForMedia(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_drive_poll_for_media");
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ sender = dbus_message_get_sender (message);
+
+ drive = NULL;
+ drives = g_volume_monitor_get_connected_drives (monitor);
+ for (l = drives; l != NULL; l = l->next)
+ {
+ char *drive_id;
+
+ drive = G_DRIVE (l->data);
+ drive_id = g_strdup_printf ("%p", drive);
+ if (strcmp (drive_id, id) == 0)
+ break;
+
+ g_free (drive_id);
+ }
+ if (l == NULL)
+ drive = NULL;
+
+ if (drive == NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.NotFound",
+ "The given drive was not found");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ if (g_object_get_data (G_OBJECT (drive), "cancellable") != NULL)
+ {
+ DBusMessage *reply;
+ reply = dbus_message_new_error (message,
+ "org.gtk.Private.RemoteVolumeMonitor.Failed",
+ "An operation is already pending");
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+ goto out;
+ }
+
+ cancellable = g_cancellable_new ();
+ g_object_set_data_full (G_OBJECT (drive), "cancellable", cancellable, g_object_unref);
+ g_object_set_data_full (G_OBJECT (cancellable), "owner", g_strdup (sender), g_free);
+ g_object_set_data_full (G_OBJECT (cancellable), "cancellation_id", g_strdup (cancellation_id), g_free);
+ outstanding_ops = g_list_prepend (outstanding_ops, cancellable);
+ g_object_weak_ref (G_OBJECT (cancellable),
+ cancellable_destroyed_cb,
+ NULL);
+
+ g_drive_poll_for_media (drive,
+ cancellable,
+ (GAsyncReadyCallback) drive_poll_for_media_cb,
+ dbus_message_ref (message));
+
+ out:
+ if (drives != NULL)
+ {
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+ }
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+handle_is_supported (DBusConnection *connection, DBusMessage *message)
+{
+ dbus_bool_t is_supported;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+
+ print_debug ("in handle_supported");
+
+ /* if monitor wasn't created on startup; try again */
+ if (monitor == NULL)
+ monitor_try_create ();
+
+ is_supported = (monitor != NULL);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &is_supported);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+handle_cancel_operation (DBusConnection *connection, DBusMessage *message)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusError dbus_error;
+ dbus_bool_t was_cancelled;
+ const char *sender;
+ const char *cancellation_id;
+ GList *l;
+
+ was_cancelled = FALSE;
+
+ sender = dbus_message_get_sender (message);
+
+ dbus_error_init (&dbus_error);
+ if (!dbus_message_get_args (message, &dbus_error,
+ DBUS_TYPE_STRING, &cancellation_id,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Error parsing args for CancelOperation(): %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ print_debug ("in handle_cancel_operation");
+
+ /* Find GCancellable to cancel */
+ for (l = outstanding_ops; l != NULL; l = l->next)
+ {
+ GCancellable *cancellable = G_CANCELLABLE (l->data);
+ const gchar *owner;
+ const gchar *id;
+
+ owner = g_object_get_data (G_OBJECT (cancellable), "owner");
+ id = g_object_get_data (G_OBJECT (cancellable), "cancellation_id");
+ if (g_strcmp0 (owner, sender) == 0 && g_strcmp0 (id, cancellation_id) == 0)
+ {
+ print_debug ("found op to cancel");
+ g_cancellable_cancel (cancellable);
+
+ was_cancelled = TRUE;
+ break;
+ }
+ }
+
+ if (!was_cancelled)
+ g_warning ("didn't find op to cancel");
+
+ out:
+ reply = dbus_message_new_method_return (message);
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &was_cancelled);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static DBusHandlerResult
+filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ DBusHandlerResult ret;
+
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameLost"))
+ {
+ /* means that someone has claimed our name (we allow replacement) */
+ g_warning ("Got NameLost, some other instance replaced us");
+ exit (0);
+ }
+ else if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ DBusMessageIter iter;
+ const gchar *name;
+ const gchar *old_owner;
+ const gchar *new_owner;
+
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &old_owner);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_get_basic (&iter, &new_owner);
+ dbus_message_iter_next (&iter);
+
+ print_debug ("NameOwnerChanged: '%s' '%s' '%s'", name, old_owner, new_owner);
+
+ if (strlen (new_owner) == 0)
+ {
+ GList *l;
+
+ /* see if @name has outstanding ops; if so, cancel them */
+ for (l = outstanding_ops; l != NULL; l = l->next)
+ {
+ GCancellable *cancellable = G_CANCELLABLE (l->data);
+ const gchar *owner;
+
+ owner = g_object_get_data (G_OBJECT (cancellable), "owner");
+ print_debug ("looking at op for %s", owner);
+ if (g_strcmp0 (owner, name) == 0)
+ {
+ print_debug ("****** name has an outstanding op");
+ g_cancellable_cancel (cancellable);
+ }
+ }
+
+ remove_name_owned_changed_for_unique_name (name);
+ }
+
+ }
+ else if (g_strcmp0 (dbus_message_get_interface (message), "org.gtk.Private.RemoteVolumeMonitor") == 0 &&
+ g_strcmp0 (dbus_message_get_path (message), "/org/gtk/Private/RemoteVolumeMonitor") == 0)
+ {
+ /* If someone is calling into this object and interface, start watching their name so
+ * we can cancel operations initiated by them when they disconnect
+ */
+ ensure_name_owner_changed_for_unique_name (dbus_message_get_sender (message));
+
+ if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "IsSupported"))
+ {
+ ret = handle_is_supported (connection, message);
+ }
+ else
+ {
+ if (monitor != NULL)
+ {
+ if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "List"))
+ ret = handle_list (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "CancelOperation"))
+ ret = handle_cancel_operation (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "MountUnmount"))
+ ret = handle_mount_unmount (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "MountOpReply"))
+ ret = handle_mount_op_reply (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "VolumeMount"))
+ ret = handle_volume_mount (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "DriveEject"))
+ ret = handle_drive_eject (connection, message);
+
+ else if (dbus_message_is_method_call (message, "org.gtk.Private.RemoteVolumeMonitor", "DrivePollForMedia"))
+ ret = handle_drive_poll_for_media (connection, message);
+
+ }
+ }
+ }
+
+ return ret;
+}
+
+typedef void (*AppendFunc) (void *object, DBusMessageIter *iter);
+
+static void
+emit_signal (DBusConnection *connection, const char *signal_name, void *object, AppendFunc func)
+{
+ char *id;
+ DBusMessage *message;
+ DBusMessageIter iter;
+
+ id = g_strdup_printf ("%p", object);
+
+ message = dbus_message_new_signal ("/org/gtk/Private/RemoteVolumeMonitor",
+ "org.gtk.Private.RemoteVolumeMonitor",
+ signal_name);
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &the_dbus_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id);
+
+ func (object, &iter);
+
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+
+
+ g_free (id);
+}
+
+static void
+drive_changed (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveChanged", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_connected (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveConnected", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_disconnected (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ emit_signal (connection, "DriveDisconnected", drive, (AppendFunc) append_drive);
+}
+
+static void
+drive_eject_button (GVolumeMonitor *monitor, GDrive *drive, DBusConnection *connection)
+{
+ g_warning ("drive eject button!");
+ emit_signal (connection, "DriveEjectButton", drive, (AppendFunc) append_drive);
+}
+
+static void
+volume_changed (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeChanged", volume, (AppendFunc) append_volume);
+}
+
+static void
+volume_added (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeAdded", volume, (AppendFunc) append_volume);
+}
+
+static void
+volume_removed (GVolumeMonitor *monitor, GVolume *volume, DBusConnection *connection)
+{
+ emit_signal (connection, "VolumeRemoved", volume, (AppendFunc) append_volume);
+}
+
+static void
+mount_changed (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountChanged", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_sniff_x_content_type (GMount *mount)
+{
+ char **x_content_types;
+ x_content_types = g_mount_guess_content_type_sync (mount, TRUE, NULL, NULL);
+ g_object_set_data_full (G_OBJECT (mount), "x-content-types", x_content_types, (GDestroyNotify) g_strfreev);
+}
+
+static void
+mount_added (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ mount_sniff_x_content_type (mount);
+ emit_signal (connection, "MountAdded", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_pre_unmount (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountPreUnmount", mount, (AppendFunc) append_mount);
+}
+
+static void
+mount_removed (GVolumeMonitor *monitor, GMount *mount, DBusConnection *connection)
+{
+ emit_signal (connection, "MountRemoved", mount, (AppendFunc) append_mount);
+}
+
+void
+g_vfs_proxy_volume_monitor_daemon_init (void)
+{
+ /* avoid loading the gio proxy module which will spawn ourselves
+ *
+ * see remote-volume-monitor-module.c
+ */
+ g_setenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE", "1", TRUE);
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ dbus_threads_init_default ();
+ g_thread_init (NULL);
+ g_type_init ();
+}
+
+
+static void
+monitor_try_create (void)
+{
+ GVolumeMonitorClass *klass;
+ GList *mounts;
+ GList *l;
+
+ monitor = NULL;
+ klass = G_VOLUME_MONITOR_CLASS (g_type_class_ref (the_volume_monitor_type));
+ if (klass == NULL)
+ {
+ g_warning ("Can't get class for type");
+ goto fail;
+ }
+
+ if (klass->is_supported != NULL)
+ {
+ if (! (klass->is_supported ()))
+ {
+ g_warning ("monitor says it's not supported");
+ goto fail;
+ }
+ }
+
+ monitor = G_VOLUME_MONITOR (g_object_new (the_volume_monitor_type, NULL));
+ if (monitor == NULL)
+ {
+ g_warning ("Cannot instantiate volume monitor");
+ goto fail;
+ }
+
+ mounts = g_volume_monitor_get_mounts (monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ mount_sniff_x_content_type (G_MOUNT (l->data));
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
+
+ fail:
+ if (klass != NULL)
+ g_type_class_unref (klass);
+}
+
+int
+g_vfs_proxy_volume_monitor_daemon_main (int argc,
+ char *argv[],
+ const char *dbus_name,
+ GType volume_monitor_type)
+{
+ int rc;
+ int ret;
+ GMainLoop *loop;
+ DBusError dbus_error;
+
+ ret = 1;
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ /* need to start up regardless of whether we can instantiate a
+ * volume monitor; this is because the proxy will need to be able to
+ * call IsSupported() on our D-Bus interface.
+ */
+
+ the_volume_monitor_type = volume_monitor_type;
+ the_dbus_name = dbus_name;
+ unique_names_being_watched = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ /* try and create the monitor */
+ monitor_try_create ();
+
+ dbus_error_init (&dbus_error);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("Cannot connect to session bus: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+
+ _g_dbus_connection_integrate_with_main (connection);
+
+ rc = dbus_bus_request_name (connection,
+ dbus_name,
+ DBUS_NAME_FLAG_ALLOW_REPLACEMENT |
+ DBUS_NAME_FLAG_DO_NOT_QUEUE |
+ DBUS_NAME_FLAG_REPLACE_EXISTING,
+ &dbus_error);
+ if (dbus_error_is_set (&dbus_error))
+ {
+ g_warning ("dbus_bus_request_name failed: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto out;
+ }
+ if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ g_warning ("Cannot become primary owner");
+ goto out;
+ }
+
+ if (!dbus_connection_add_filter (connection, filter_function, NULL, NULL))
+ {
+ g_warning ("Cannot add filter function");
+ goto out;
+ }
+
+ if (monitor != NULL)
+ {
+ g_signal_connect (monitor, "drive-changed", (GCallback) drive_changed, connection);
+ g_signal_connect (monitor, "drive-connected", (GCallback) drive_connected, connection);
+ g_signal_connect (monitor, "drive-disconnected", (GCallback) drive_disconnected, connection);
+ g_signal_connect (monitor, "drive-eject-button", (GCallback) drive_eject_button, connection);
+
+ g_signal_connect (monitor, "volume-changed", (GCallback) volume_changed, connection);
+ g_signal_connect (monitor, "volume-added", (GCallback) volume_added, connection);
+ g_signal_connect (monitor, "volume-removed", (GCallback) volume_removed, connection);
+
+ g_signal_connect (monitor, "mount-changed", (GCallback) mount_changed, connection);
+ g_signal_connect (monitor, "mount-added", (GCallback) mount_added, connection);
+ g_signal_connect (monitor, "mount-pre-unmount", (GCallback) mount_pre_unmount, connection);
+ g_signal_connect (monitor, "mount-removed", (GCallback) mount_removed, connection);
+ }
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ ret = 0;
+
+out:
+ return ret;
+}
diff --git a/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.h b/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.h
new file mode 100644
index 00000000..d6c767db
--- /dev/null
+++ b/trunk/monitor/proxy/gvfsproxyvolumemonitordaemon.h
@@ -0,0 +1,35 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __G_VFS_PROXY_VOLUME_MONITOR_DAEMON_H__
+#define __G_VFS_PROXY_VOLUME_MONITOR_DAEMON_H__
+
+#include <gio/gio.h>
+
+void g_vfs_proxy_volume_monitor_daemon_init (void);
+int g_vfs_proxy_volume_monitor_daemon_main (int argc,
+ char *argv[],
+ const char *dbus_name,
+ GType volume_monitor_type);
+
+#endif
diff --git a/trunk/monitor/proxy/remote-volume-monitor-module.c b/trunk/monitor/proxy/remote-volume-monitor-module.c
new file mode 100644
index 00000000..42325278
--- /dev/null
+++ b/trunk/monitor/proxy/remote-volume-monitor-module.c
@@ -0,0 +1,75 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include "gproxyvolumemonitor.h"
+#include "gproxyvolume.h"
+#include "gproxymount.h"
+#include "gproxyshadowmount.h"
+#include "gproxydrive.h"
+
+void
+g_io_module_load (GIOModule *module)
+{
+ /* see gvfsproxyvolumemonitor.c:g_vfs_proxy_volume_monitor_daemon_init() */
+ if (g_getenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE") != NULL)
+ goto out;
+
+ /* We make this module resident since we *may* hold on to an instance
+ * of the union monitor in the static method get_mount_for_mount_path()
+ * on GNativeVolumeMonitor. And it doesn't make much sense to unload
+ * the module *anyway*.
+ *
+ * See the comment gproxyvolumemonitor.c:get_mount_for_mount_path().
+ */
+ g_type_module_use (G_TYPE_MODULE (module));
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ g_proxy_drive_register (module);
+ g_proxy_mount_register (module);
+ g_proxy_shadow_mount_register (module);
+ g_proxy_volume_register (module);
+ g_proxy_volume_monitor_register (module);
+out:
+ ;
+ }
+
+void
+g_io_module_unload (GIOModule *module)
+{
+ if (g_getenv ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE") != NULL)
+ goto out;
+
+ g_proxy_volume_monitor_teardown_session_bus_connection ();
+
+out:
+ ;
+}
diff --git a/trunk/po/.gitignore b/trunk/po/.gitignore
new file mode 100644
index 00000000..6c59253f
--- /dev/null
+++ b/trunk/po/.gitignore
@@ -0,0 +1,14 @@
+*.gmo
+*.mo
+*.pot
+Makefile
+Makefile.in
+Makefile.in.in
+POTFILES
+po2tbl.sed
+po2tbl.sed.in
+cat-id-tbl.c
+stamp-cat-id
+stamp-it
+messages
+missing
diff --git a/trunk/po/ChangeLog b/trunk/po/ChangeLog
new file mode 100644
index 00000000..44c95689
--- /dev/null
+++ b/trunk/po/ChangeLog
@@ -0,0 +1,1576 @@
+2009-03-16 Amitakhya Phukan <amitakhya@svn.gnome.org>
+
+ * LINGUAS: Added as
+ * as.po: Updated Assamese translations.
+
+2009-03-15 Ankitkumar Patel <ankit@redhat.com>
+
+ * gu.po: Updated Gujarati Translations.
+
+2009-03-14 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+
+ * ru.po: Updated Russian translation by Yuriy Penkin.
+
+2009-03-14 Wadim Dziedzic <wdziedzic@aviary.pl>
+
+ * pl.po: Updated Polish translation
+
+2009-03-13 Sandeep Shedmake <sshedmak@redhat.com>
+
+ * mr.po: Updated Marathi Translations.
+
+2009-03-13 felix@redhat.com>
+
+ * ta.po: Tamil Translation updated by Thirumurthi vasudevan
+
+=== gvfs 1.1.8 ===
+
+2009-03-10 Runa Bhattacharjee <runab@redhat.com>
+
+ * bn_IN.po: Updated Bengali India Translation
+
+2009-03-10 Hendrik Richter <hendrikr@gnome.org>
+
+ * de.po: Updated German translation.
+
+2009-03-09 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2009-03-09 Manoj Kumar Giri <mgiri@redhat.com>
+
+ * or.po: Updated Oriya Translation
+
+2009-03-08 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2009-03-08 Gintautas Miliauskas <gintas@akl.lt>
+
+ * lt.po: Updated Lithuanian translation.
+
+2009-03-06 Manoj Kumar Giri <mgiri@redhat.com>
+
+ * or.po: Updated Oriya Translation.
+ * LINGUAS: Added Oriya (or) in the list.
+
+2009-03-03 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+=== gvfs 1.1.7 ===
+
+2009-03-02 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Add new files
+
+2009-02-27 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2009-02-25 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2009-02-23 Philip Withnall <philip@tecnocode.co.uk>
+
+ * en_GB.po: Updated British English translation.
+
+2009-02-23 Og Maciel <ogmaciel@gnome.org>
+
+ * pt_BR.po: Updated Brazilian Portuguese translation by
+ Vladimir Melo.
+
+2009-02-22 Baris Cicek <baris@teamforce.name.tr>
+
+ * tr.po: Updated Turkish translation.
+
+2009-02-19 Sweta Kothari <swkothar@redhat.com>
+
+ * gu.po: Committed Gujarati Translation.
+
+2009-02-19 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2009-02-18 Jani Monoses <jani@ubuntu.com>
+
+ * ro.po: Updated Romanian translation
+ by Adi Roiban <adi@roiban.ro>
+
+2009-02-18 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Updated Korean translation.
+
+2009-02-18 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation by Ihar Hrachyshka.
+
+=== gvfs 1.1.6 ===
+
+2009-02-15 Tomasz Dominikowski <tdominikowski@aviary.pl>
+
+ * pl.po: Updated Polish translation
+
+2009-02-15 Kenneth Nielsen <k.nielsen81@gmail.com>
+
+ * da.po: Updated Danish translation by Ask H. Larsen
+
+2009-02-14 Claude Paroz <claude@2xlibre.net>
+
+ * fr.po: Updated French translation.
+
+2009-02-14 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2009-02-12 Jani Monoses <jani@ubuntu.com>
+
+ * LINGUAS:
+ * ro.po: Added Romanian translation
+ by Adi Roiban <adi@roiban.ro>
+
+2009-02-12 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2009-02-12 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2009-02-12 Gabor Kelemen <kelemeng@gnome.hu>
+
+ * hu.po: Translation updated.
+
+2009-02-11 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2009-02-11 Alexander Shopov <ash@contact.bg>
+
+ * bg.po: Updated Bulgarian translation by
+ Alexander Shopov <ash@contact.bg>
+
+2009-02-10 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2009-02-09 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2009-02-09 Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>
+
+ * zh_HK.po: Updated Traditional Chinese translation(Hong Kong).
+ * zh_TW.po: Updated Traditional Chinese translation(Taiwan).
+
+2009-02-07 Clytie Siddall <clytie@riverland.net.au>
+
+ * vi.po: Updated Vietnamese translation.
+
+2009-02-04 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation.
+
+2009-02-04 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Dutch translation updated by Wouter Bolsterlee.
+
+2009-02-04 Krishnababu K <kkrothap@redhat.com>
+
+ * te.po: Updated Telugu Translation.
+
+2009-02-02 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation.
+
+=== gvfs 1.1.5 ===
+
+2009-01-29 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Updated Korean translation.
+
+2009-01-26 Nikos Charonitakis <nikosx@gmail.com>
+
+ * el.po: Updated Greek translation .
+
+2009-01-26 Nikos Charonitakis <nikosx@gmail.com>
+
+ * el.po: Updated Greek translation.
+
+2009-01-22 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+=== gvfs 1.1.4 ===
+
+2009-01-12 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2009-01-08 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2009-01-06 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation.
+
+=== gvfs 1.1.3 ===
+
+2009-01-05 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2009-01-03 甘露(Gan Lu) <rhythm.gan@gmail.com>
+
+ * zh_CN.po: Updated Chinese Simplified translation
+
+2009-01-04 Raivis Dejus <orvils@gmail.com>
+
+ * lv.po: Added latvian translation
+ * LINGUAS: Added 'lv' for Latvian translations
+
+2008-12-16 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation.
+
+2008-12-15 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+=== gvfs 1.1.2 ===
+
+2008-12-09 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-12-08 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2008-12-06 Leonardo Ferreira Fontenelle <leonardof@gnome.org>
+
+ * pt_BR.po: Updated Brazilian translation by Daniel S. Koda.
+
+2008-12-06 Alexander Shopov <ash@contact.bg>
+
+ * bg.po: Updated Bulgarian translation by
+ Alexander Shopov <ash@contact.bg>
+
+2008-12-01 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+=== gvfs 1.1.1 ===
+
+2008-12-01 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Add missing files
+
+2008-11-28 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2008-11-22 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-11-08 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation.
+
+2008-10-22 Simos Xenitellis <simos@gnome.org>
+
+ * el.po: Updated Greek translation by Nick Agianniotis.
+
+2008-10-16 Marcel Telka <marcel@telka.sk>
+
+ * sk.po: Updated Slovak translation by Pavol Šimo.
+
+2008-10-11 Leonardo Ferreira Fontenelle <leonardof@gnome.org>
+
+ * pt_BR.po: Fixed terminology in Brazilian Portuguese translation by
+ Vladimir Melo.
+
+2008-09-27 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2008-09-21 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+
+ * ru.po: Updated Russian translation by Yuriy Penkin.
+
+2008-09-20 Kenneth Nielsen <k.nielsen81@gmail.com>
+
+ * da.po: Updated Danish translation by Ask H. Larsen
+
+2008-09-19 Shankar Prasad <svenkate@redhat.com>
+
+ * kn.po: Added Kannada Translation
+ * LINGUAS: Added kn to list of Languges
+
+2008-09-18 Baris Cicek <baris@teamforce.name.tr>
+
+ * tr.po: Updated Turkish Translation
+
+2008-09-17 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Updated Korean translation by Young-Ho Cha.
+
+2008-09-17 Gabor Kelemen <kelemeng@gnome.hu>
+
+ * hu.po: Translation updated.
+
+2008-09-16 Laurent Dhima <laurenti@alblinux.net>
+
+ * LINGUAS, sq.po: Added Albanian translation.
+
+2008-09-15 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+2008-09-14 Alexander Shopov <ash@contact.bg>
+
+ * bg.po: Updated Bulgarian translation by
+ Alexander Shopov <ash@contact.bg>
+
+2008-09-14 Goran Rakić <grakic@devbase.net>
+
+ * LINGUAS, sr.po, sr@latin.po: Added Serbian Translation.
+
+2008-09-14 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-09-14 Gintautas Miliauskas <gintas@akl.lt>
+
+ * lt.po: Updated Lithuanian translation.
+
+=== gvfs 0.99.7 ===
+
+2008-09-08 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2008-09-07 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-09-07 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-09-04 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+=== gvfs 0.99.6 ===
+
+2008-09-01 Hans Petter Jansson <hpj@novell.com>
+
+ * POTFILES.in: Remove dead file gvfsjobupload.c and add replacement
+ gvfsjobpull.c and gvfsjobpush.c.
+
+2008-09-01 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-08-30 Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>
+
+ * zh_HK.po: Updated Traditional Chinese translation(Hong Kong).
+ * zh_TW.po: Updated Traditional Chinese translation(Taiwan).
+
+2008-08-28 Seán de Búrca <sdeburca@svn.gnome.org>
+
+ * ga.po: Added Irish translation.
+ * LINGUAS: Added Irish.
+
+2008-08-28 Hendrik Richter <hendrikr@gnome.org>
+
+ * de.po: Updated German translation.
+
+2008-08-28 Hendrik Richter <hendrikr@gnome.org>
+
+ * de.po: Updated German translation.
+
+2008-08-27 Jovan Naumovski <jovan@lugola.net>
+
+ * mk.po: Updated Macedonian translation.
+
+2008-08-27 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-08-26 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation by Mark Krapivner.
+
+2008-08-25 Robert-André Mauchin <zebob.m@pengzone.org>
+
+ * fr.po: Updated French translation.
+
+2008-08-24 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
+
+ * vi.po: Updated Vietnamese translation
+
+2008-08-24 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2008-08-24 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-08-23 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-08-23 Priit Laes <plaes at svn dot gnome dot org>
+
+ * et.po: Translation updated by Ivar Smolin
+
+2008-08-22 Og Maciel <ogmaciel@gnome.org>
+
+ * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo.
+
+2008-08-22 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-08-21 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ gl.po: Updated Galician translation
+
+2008-08-21 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+=== gvfs 0.99.5 ===
+
+2008-08-16 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation by Ihar Hrachyshka.
+
+2008-08-16 Priit Laes <plaes at svn dot gnome dot org>
+
+ * et.po: Translation updated by Ivar Smolin
+
+2008-08-16 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-08-15 Og Maciel <ogmaciel@gnome.org>
+ * pt_BR.po: Updated translation by Vladimir Melo.
+
+2008-08-15 Tomasz Dominikowski <tdominikowski@aviary.pl>
+ * pl.po: Updated Polish translation.
+
+2008-08-15 Praveen Arimbrathodiyil <pravi.a@gmail.com>
+
+ * ml.po: Malayalam translation update by Harivishnu
+
+2008-08-14 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-08-13 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-08-12 Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>
+
+ * zh_HK.po: Updated Traditional Chinese translation(Hong Kong).
+ * zh_TW.po: Updated Traditional Chinese translation(Taiwan).
+
+2008-08-09 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2008-08-08 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ gl.po: Updated Galician translation
+
+2008-08-07 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-08-07 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Fixed a typo.
+
+2008-08-06 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2008-08-06 Sweta Kothari <swkothar@redhat.com>
+
+ * gu.po: Added Gujarati Translation.
+
+2008-08-06 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-08-05 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+=== gvfs 0.99.4 ===
+
+2008-08-04 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated italian translation.
+
+2008-08-03 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician translation
+
+2008-08-03 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-08-01 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2008-07-29 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-07-25 Leonardo Ferreira Fontenelle <leonardof@gnome.org>
+
+ * pt_BR.po: Terminology improvements by Vladimir Melo.
+
+=== gvfs 0.99.2 ===
+
+2008-07-08 David Zeuthen <davidz@redhat.com>
+
+ * POTFILES.in: hal/*.c moved to monitor/hal/*.c
+
+2008-06-14 Andre Klapper <a9016009@gmx.de>
+
+ * POTFILES.in: added programs/gvfs-mkdir.c.
+
+2008-06-11 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-06-05 Clytie Siddall <clytie@riverland.net.au>
+
+ * vi.po: Updated Vietnamese translation.
+
+2008-06-05 Priit Laes <plaes at svn dot gnome dot org>
+
+ * et.po: Translation updated by Ivar Smolin
+
+=== gvfs 0.99.1 ===
+
+2008-06-02 Clytie Siddall <clytie@riverland.net.au>
+
+ * vi.po: Added Vietnamese translation (and in LINGUAS).
+
+2008-05-22 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-05-22 Priit Laes <plaes at svn dot gnome dot org>
+
+ * et.po: Translation updated by Ivar Smolin
+
+2008-05-19 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Djihed Afifi.
+
+2008-05-08 Alexander Shopov <ash@contact.bg>
+
+ * LINGUAS: Added bg (Bulgarian)
+
+2008-04-27 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2008-04-21 Kjartan Maraas <kmaraas@gnome.org>
+
+ * POTFILES.in: Add hal-utils.c
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-04-10 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po: Updated Hebrew translation.
+
+2008-04-01 Priit Laes <plaes at svn dot gnome dot org>
+
+ * et.po: Translation updated by Ivar Smolin
+
+2008-03-31 Baris Cicek <baris@teamforce.name.tr>
+
+ * tr.po: Updated Turkish translation
+
+=== gvfs 0.2.2 ===
+
+2008-03-31 Eskild Hustvedt <eskildh@gnome.org>
+
+ * nn.po: Added Norwegian Nynorsk translation
+
+2008-03-28 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-03-20 Erdal Ronahi <erdal dot ronahi at gmail dot com>
+
+ * LINGUAS: Added ku to list of languages
+ * ku.po: Added initial Kurdish translations
+
+2008-03-12 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Added gvfsbackenddaemon.c
+
+2008-03-10 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * fr.po: Updated French translation.
+
+2008-03-10 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+=== gvfs 0.2.0.1 ===
+
+2008-03-10 Kostas Papadimas <pkst@gnome.org>
+
+ * el.po: Updated Greek translation
+
+2008-03-10 Gabor Kelemen <kelemeng@gnome.hu>
+
+ * hu.po: Translation updated
+
+2008-03-09 Kenneth Nielsen <k.nielsen81@gmail.com>
+
+ * LUNGUAS: Added da to list of languages
+ * da.po: Added Danish translation
+
+2008-03-09 Gabor Kelemen <kelemeng@gnome.hu>
+
+ * hu.po: Translation updated
+
+2008-03-09 Marcel Telka <marcel@telka.sk>
+
+ * sk.po: Added Slovak translation by Pavol Šimo.
+ * LINGUAS: Added sk (Slovak).
+
+2008-03-09 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-03-09 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * fr.po: Updated French translation.
+
+2008-03-09 Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>
+
+ * zh_HK.po: Updated Traditional Chinese translation(Hong Kong).
+ * zh_TW.po: Updated Traditional Chinese translation(Taiwan).
+
+2008-03-09 Artur Flinta <aflinta@gmail.com>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-03-09 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2008-03-09 Gintautas Miliauskas <gintas@akl.lt>
+
+ * lt.po: Updated Lithuanian translation.
+
+2008-03-08 Wadim Dziedzic <wadimd@svn.gnome.org>
+
+ * pl.po: Updated polish translation
+
+2008-03-08 Simos Xenitellis <simos@gnome.org>
+
+ * el.po: Added Greek translation.
+ * LINGUAS: Added (el) Greek.
+
+2008-03-8 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Djihed Afifi.
+
+2008-03-08 Runa Bhattacharjee <runab@fedoraproject.org>
+
+ * bn_IN.po: Updated Bengali India Translations by Sankarshan Mukhopdhyay
+
+2008-03-08 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2008-03-08 Maxim Dziumanenko <dziumanenko@gmail.com>
+
+ * uk.po: Added Ukrainian translation.
+ * LINGUAS: Added Ukrainian (uk) to the list of languages
+
+2008-03-07 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-03-07 Arangel Angov <arangel@linux.net.mk>
+
+ * mk.po: Updated Macedonian translation.
+
+2008-03-07 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-03-07 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-03-07 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-03-07 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation.
+
+2008-03-07 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Updated Korean translation by Young-Ho Cha.
+
+2008-03-07 Gintautas Miliauskas <gintas@akl.lt>
+
+ * lt.po: Updated Lithuanian translation.
+
+2008-03-07 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-03-07 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+2008-03-06 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-03-06 Philip Withnall <pwithnall@svn.gnome.org>
+
+ * en_GB.po: Updated British English translation.
+
+2008-03-06 Marcel Telka <marcel@telka.sk>
+
+ * POTFILES.in: Added missing files.
+
+2008-03-06 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-03-06 I. Felix <ifelix@svn.gnome.org>
+
+ * ta.po: Tamil Translation updated by Tirumurthi Vasudevan
+
+2008-03-06 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-03-06 Runa Bhattacharjee <runab@fedoraproject.org>
+
+ * bn_IN: Correction of header section for plural form
+
+2008-03-05 Runa Bhattacharjee <runab@fedoraproject.org>
+
+ * bn_IN.po: Added Bengali India Translations by Sankarshan Mukhopadhyay
+ * LINGUAS: Added Bengali India (bn_IN) to the list of languages
+
+2008-03-05 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2008-03-05 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-03-05 Rahul Bhalerao <b.rahul.pm@gmail.com>
+
+ * mr.po: Updated Marathi Translations by Sandeep Shedmake.
+
+2008-03-04 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+=== gvfs 0.1.11 ===
+=== gvfs 0.1.10 ===
+
+2008-03-04 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-03-04 Rajesh Ranjan <rajeshkajha@yahoo.com>
+
+ * hi.po: Added Hindi translation.
+
+=== gvfs 0.1.9 ===
+
+2008-03-04 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-03-03 Philip Withnall <pwithnall@svn.gnome.org>
+
+ * en_GB.po: Updated British English translation.
+
+2008-03-03 Rahul Bhalerao <b.rahul.pm@gmail.com>
+
+ * mr.po: Updated Marathi translations from Sandeep Shedmake.
+
+2008-03-03 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+2008-03-03 Leonid Kanter <leon@asplinux.ru>
+
+ * ru.po: Updated Russian translation
+
+2008-03-03 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-03-03 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-03-03 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-03-03 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * fr.po: Updated French translation by Robert-André Mauchin and
+ Stéphane Raimbault.
+
+2008-03-03 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation.
+
+2008-03-03 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-03-02 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-03-02 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-03-02 Philip Withnall <pwithnall@svn.gnome.org>
+
+ * LINGUAS: Added en_GB (British English).
+ * en_GB.po: Added British English translation.
+
+2008-03-02 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Updated Czech translation.
+
+2008-03-02 Gintautas Miliauskas <gintas@akl.lt>
+
+ * LINGUAS: Added Lithuanian (lt).
+ * lt.po: Updated Lithuanian translation.
+
+2008-03-02 Arangel Angov <arangel@linux.net.mk>
+
+ * mk.po: Updated Macedonian translation.
+
+2008-03-01 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-03-01 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-03-01 Jonh Wendell <jwendell@gnome.org>
+
+ * pt_BR: Updated Brazilian Portuguese translation.
+
+2008-03-01 Artur Flinta <aflinta@gmail.com>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-03-01 Artur Flinta <aflinta@gmail.com>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-03-01 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-03-01 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-29 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * ja.po: Updated Japanese translation.
+
+2008-02-29 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-02-29 Ani Peter <peter.ani@gmail.com>
+
+ * ml.po: Updated Malayalam Translation
+ * LINGUAS: Added Malayalam (ml)
+
+2008-02-29 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-02-29 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-29 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-02-29 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Updated Korean translation by Young-Ho Cha.
+
+2008-02-29 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-02-28 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-28 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+2008-02-28 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-28 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-28 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+2008-02-28 Jonh Wendell <jwendell@gnome.org>
+
+ * pt_BR: Updated Brazilian Portuguese translation.
+
+2008-02-28 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-27 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-02-27 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * fr.po: Updated French translation.
+
+2008-02-27 Bastien Nocera <hadess@hadess.net>
+
+ * POTFILES.in: update for the obexftp backend, no
+ new strings though
+
+2008-02-27 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-02-27 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-02-27 Arangel Angov <arangel@linux.net.mk>
+
+ * mk.po: Updated Macedonian translation.
+
+2008-02-26 Jonh Wendell <jwendell@gnome.org>
+
+ * pt_BR: Updated Brazilian Portuguese translation.
+
+2008-02-26 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-02-26 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Djihed Afifi.
+
+2008-02-26 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+2008-02-26 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-02-26 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-26 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+=== gvfs 0.1.8 ===
+
+2008-02-25 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-25 Andre Klapper <a9016009@gmx.de>
+
+ * POTFILES.in: added missing daemon/gvfsbackendgphoto2.c.
+
+2008-02-25 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-02-25 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-25 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-02-25 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-25 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-24 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+2008-02-24 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Updated Dutch translation by Wouter Bolsterlee.
+
+2008-02-24 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * POTFILES.in: Add missing file to POTFILES.in. This
+ string freeze break was approved by the Gnome i18n team.
+
+2008-02-23 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-23 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * fr.po: Updated French translation by Robert-André Mauchin.
+
+2008-02-22 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-23 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * th.po: Updated Thai translation.
+
+2008-02-22 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-02-23 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation.
+
+2008-02-22 Artur Flinta <aflinta@gmail.com>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-02-22 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-22 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-22 Takeshi AIHANA <takeshi.aihana@gmail.com>
+
+ * LINGUAS: Added 'ja' (Japanese).
+ * ja.po: Added Japanese translation.
+
+2008-02-22 Jonh Wendell <jwendell@gnome.org>
+
+ * pt_BR: Updated Brazilian Portuguese translation.
+
+2008-02-22 Jonh Wendell <jwendell@gnome.org>
+
+ * POTFILES.in: Added daemon/gvfsbackendnetwork.c
+ * po/: Added some files to the svn ignore list
+
+2008-02-22 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-22 Amanpreet Singh Alam <apreet.alam@gmail.com>
+
+ * pa.po: Punjabi Translation Added
+ * LINGUAS: 'pa' Added to list
+
+2008-02-22 Arangel Angov <arangel@linux.net.mk>
+
+ * mk.po: Updated Macedonian translation.
+
+2008-02-21 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-02-21 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Updated Belarusian Latin translation.
+
+2008-02-21 Theppitak Karoonboonyanan <thep@linux.thai.net>
+
+ * LINGUAS: Added th (Thai).
+ * th.po: Added Thai translation.
+
+2008-02-21 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+2008-02-20 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-02-20 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-20 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-20 Changwoo Ryu <cwryu@debian.org>
+
+ * ko.po: Added Korean translation by Young-Ho Cha.
+ * LINGUAS: Added ko (Korean)
+
+2008-02-19 Baris Cicek <baris@teamforce.name.tr>
+
+ * tr.po: Added Turkish translation from Anil Karadag
+ * LINGUAS: Added tr (Turkish)
+
+2008-02-11 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation, fixed typos thanks to Ignacio
+ Casal Quinteiro.
+
+2008-02-19 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * gl.po: Updated Galician Translation.
+
+2008-02-18 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-02-18 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-02-18 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Updated Finnish translation.
+
+2008-02-18 Ihar Hrachyshka <booxter@lacinka.org>
+
+ * be@latin.po: Added Belarusian Latin translation.
+ * LINGUAS: Added be@latin.
+
+2008-02-17 Wouter Bolsterlee <wbolster@svn.gnome.org>
+
+ * nl.po: Added Dutch translation by Wouter Bolsterlee.
+
+2008-02-17 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Djihed Afifi.
+
+2008-02-17 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Updated Catalan translation.
+
+2008-02-16 Petr Kovar <pknbe@volny.cz>
+
+ * cs.po: Added Czech translation.
+ * LINGUAS: Added cs.
+
+2008-02-16 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-02-15 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-15 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-14 Rahul Bhalerao <b.rahul.pm@gmail.com>
+
+ * mr.po: Added Marathi translations by Sandeep Shedmake.
+ * LINGUAS: Added an entry for Marathi (mr).
+
+2008-02-14 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-02-13 Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>
+
+ * LINGUAS: add zh_HK zh_TW
+ * zh_HK.po: Added Traditional Chinese translation(Hong Kong).
+ * zh_TW.po: Added Traditional Chinese translation(Taiwan).
+
+2008-02-13 Ilkka Tuohela <hile@iki.fi>
+
+ * fi.po: Added Finnish translation.
+
+2008-02-12 Artur Flinta <aflinta@svn.gnome.org>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-02-11 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+=== gvfs 0.1.7 ===
+
+2008-02-11 Leonid Kanter <leon@asplinux.ru>
+
+ * ru.po: Updated Rusian translation
+
+2008-02-11 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-11 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-02-10 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+2008-02-10 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-09 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Updated Portuguese translation.
+
+2008-02-09 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-02-09 Gabor Kelemen <kelemeng@gnome.hu>
+
+ * hu.po: Translation added
+ * LINGUAS: hu added
+
+2008-02-08 Artur Flinta <aflinta@svn.gnome.org>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-02-08 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-02-07 Artur Flinta <aflinta@svn.gnome.org>
+
+ * pl.po: Updated Polish translation by GNOME PL Team.
+
+2008-02-07 Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+
+ * LINGUAS: Added gl.
+ * gl.po: Added Galician Translation.
+
+2008-02-05 Stéphane Raimbault <stephane.raimbault@gmail.com>
+
+ * LINGUAS: Added fr.
+ * fr.po: Added French translation by Claude Paroz.
+
+2008-02-04 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation
+
+2008-02-04 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-02-02 Yair Hershkovitz <yairhr@gmail.com>
+
+ * he.po, LINGUAS: Added Hebrew translation.
+
+2008-02-02 Hendrik Brandt <heb@gnome-de.org>
+
+ * de.po: Updated German translation.
+
+2008-01-31 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-01-31 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-01-29 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-29 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Added gvfs-open.c
+
+2008-01-29 Jonh Wendell <jwendell@gnome.org>
+
+ * LINGUAS, pt_BR.po: Brazilian Portuguese translation by Enrico Nicoletto.
+
+=== gvfs 0.1.6 ===
+
+2008-01-29 Jovan Naumovski <jovan@lugola.net>
+
+ * mk.po: Added Macedonian translation.
+
+2008-01-28 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Updated Swedish translation.
+
+=== gvfs 0.1.5 ===
+
+2008-01-28 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-27 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Updated Arabic Translation by Khaled Hosny.
+
+2008-01-27 Kjartan Maraas <kmaraas@gnome.org>
+
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-01-26 Duarte Loreto <happyguy_pt@hotmail.com>
+
+ * pt.po: Added Portuguese translation.
+ * LINGUAS: Added Portuguese (pt) to list.
+
+2008-01-26 Matej Urbančič <mateju@svn.gnome.org>
+
+ * sl.po: Added Slovenian translation
+ * LINGUAS: Added sl
+
+2008-01-25 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-01-25 I. Felix <ifelix@svn.gnome.org>
+
+ * ta.po: Tamil Translation updated by Thangamani Arul
+ * LINGUAS: Added Tamil (ta) to The List of Languages.
+
+2008-01-24 Alexander Larsson <alexl@redhat.com>
+
+ * LINGUAS: Added.
+
+2008-01-24 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-01-24 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Fixed translation to pass msgfmt -cv.
+
+2008-01-22 Gil Forcada <gforcada@gnome.org>
+
+ * ca.po: Added Catalan translation with lots of help from David Planella.
+
+2008-01-22 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-22 Johannes Schmid <jhs@gnome.org>
+
+ * de.po: Updated German translation
+
+2008-01-21 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+=== gvfs 0.1.4 ===
+2008-01-21 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Add new files
+
+2008-01-18 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-18 Luca Ferretti <elle.uca@libero.it>
+
+ * POTFILES.in: Added programs/gvfs-cat.c
+
+2008-01-17 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-16 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-16 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Updated Basque translation.
+
+2008-01-15 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-01-15 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-15 Daniel Nylander <po@danielnylander.se>
+
+ * sv.po: Added Swedish translation.
+
+2008-01-14 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+=== gvfs 0.1.2 ===
+
+2008-01-14 Kjartan Maraas <kmaraas@gnome.org>
+
+ * POTFILES.in: Add missing file.
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-01-13 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-13 Andre Klapper <a9016009@gmx.de>
+
+ * de.po: Added German translation.
+
+2008-01-12 Leonid Kanter <leon@asplinux.ru>
+
+ * ru.po: Added Russian translation
+
+2008-01-12 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Updated Italian translation.
+
+2008-01-12 Luca Ferretti <elle.uca@libero.it>
+
+ * POTFILES.in: Added new gvfsbackendhttp.c
+
+2008-01-12 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Updated Spanish translation
+
+2008-01-11 Inaki Larranaga Murgoitio <dooteo@euskalgnu.org>
+
+ * eu.po: Added Basque translation.
+
+2008-01-11 Jorge Gonzalez <jorgegonz@svn.gnome.org>
+
+ * es.po: Added initial Spanish translation
+ * LINGUAS: Added es.
+
+2008-01-11 Kjartan Maraas <kmaraas@gnome.org>
+
+ * POTFILES.in: Add missing file.
+ * nb.po: Updated Norwegian bokmål translation.
+
+2008-01-10 Djihed Afifi <djihed@gmail.com>
+
+ * ar.po: Added Arabic Translation.
+ * LINGUAS: Added ar.
+
+2008-01-09 Luca Ferretti <elle.uca@libero.it>
+
+ * Makefile.in.in:
+
+ Removed, autogenerated using intltool by now.
+
+ * POTFILES.in:
+
+ Added new missing files for computer:// backend.
+
+=== gvfs 0.1.1 ===
+
+2007-12-27 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Remove intltool option, since we don't use intltool.
+
+2007-12-21 Kjartan Maraas <kmaraas@gnome.org>
+
+ * POTFILES.in: Add missing file.
+ * nb.po: Add Norwegian bokmål translation.
+
+=== gvfs 0.1.0 ===
+
+2007-12-20 Alexander Larsson <alexl@redhat.com>
+
+ * Makefile.in.in: Added.
+ * POTFILES.in:
+ * it.po:
+ Add Makefile.in.in
+
+2007-12-18 Luca Ferretti <elle.uca@libero.it>
+
+ * POTFILES.in: revert previous commit: gvfs is not using
+ intltool. The question is: should it???
+
+2007-12-18 Luca Ferretti <elle.uca@libero.it>
+
+ * POTFILES.in: prepend "[encoding: UTF-8]" to make
+ intltool-update happy.
+
+2007-12-18 Luca Ferretti <elle.uca@libero.it>
+
+ * POTFILES.in: remove duplicate entries and add missing files
+ [recentrly added: daemon/gvfsjobunmount.c hal/ghaldrive.c
+ hal/ghalmount.c hal/ghalvolume.c hal/ghalvolumemonitor.c]
+
+2007-12-18 Luca Ferretti <elle.uca@libero.it>
+
+ * it.po: Added Italian translation.
+
+=== gvfs 0.0.2 ===
+
+2007-11-15 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Remove wrongly added files from failed distcheck
+
+2007-11-06 Alexander Larsson <alexl@redhat.com>
+
+ * POTFILES.in:
+ Added all source files
+
+
diff --git a/trunk/po/LINGUAS b/trunk/po/LINGUAS
new file mode 100644
index 00000000..d82bbbb6
--- /dev/null
+++ b/trunk/po/LINGUAS
@@ -0,0 +1,58 @@
+# please keep this list sorted alphabetically
+ar
+as
+be@latin
+bg
+bn_IN
+ca
+cs
+da
+de
+el
+en_GB
+es
+eu
+et
+fi
+fr
+ga
+gl
+gu
+he
+hu
+hi
+it
+ja
+kn
+ko
+ku
+lt
+lv
+mk
+ml
+mr
+nb
+nl
+nn
+or
+pa
+pl
+pt
+pt_BR
+ro
+ru
+sk
+sl
+sq
+sr
+sr@latin
+sv
+ta
+te
+th
+tr
+uk
+vi
+zh_CN
+zh_HK
+zh_TW
diff --git a/trunk/po/POTFILES.in b/trunk/po/POTFILES.in
new file mode 100644
index 00000000..b08e385e
--- /dev/null
+++ b/trunk/po/POTFILES.in
@@ -0,0 +1,91 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+[encoding: UTF-8]
+client/gdaemonfile.c
+client/gdaemonfileenumerator.c
+client/gdaemonfileinputstream.c
+client/gdaemonfileoutputstream.c
+client/gdaemonvfs.c
+client/gvfsdaemondbus.c
+client/gvfsiconloadable.c
+common/gmounttracker.c
+common/gsysutils.c
+common/gvfsdaemonprotocol.c
+common/gvfsdnssdresolver.c
+common/gvfsdnssdutils.c
+common/gvfsicon.c
+daemon/daemon-main.c
+daemon/gvfsbackend.c
+daemon/gvfsbackendarchive.c
+daemon/gvfsbackendburn.c
+daemon/gvfsbackendcdda.c
+daemon/gvfsbackendcomputer.c
+daemon/gvfsbackenddav.c
+daemon/gvfsbackenddnssd.c
+daemon/gvfsbackendftp.c
+daemon/gvfsbackendgphoto2.c
+daemon/gvfsbackendhttp.c
+daemon/gvfsbackendlocaltest.c
+daemon/gvfsbackendnetwork.c
+daemon/gvfsbackendobexftp.c
+daemon/gvfsbackendsftp.c
+daemon/gvfsbackendsmb.c
+daemon/gvfsbackendsmbbrowse.c
+daemon/gvfsbackendtest.c
+daemon/gvfsbackendtrash.c
+daemon/gvfschannel.c
+daemon/gvfsdaemon.c
+daemon/gvfsdaemonutils.c
+daemon/gvfsjobcloseread.c
+daemon/gvfsjobclosewrite.c
+daemon/gvfsjobcopy.c
+daemon/gvfsjobcreatemonitor.c
+daemon/gvfsjobdbus.c
+daemon/gvfsjobdelete.c
+daemon/gvfsjobenumerate.c
+daemon/gvfsjobmakedirectory.c
+daemon/gvfsjobmakesymlink.c
+daemon/gvfsjobmount.c
+daemon/gvfsjobmountmountable.c
+daemon/gvfsjobmove.c
+daemon/gvfsjobopenforread.c
+daemon/gvfsjobopenforwrite.c
+daemon/gvfsjobopeniconforread.c
+daemon/gvfsjobpull.c
+daemon/gvfsjobpush.c
+daemon/gvfsjobqueryattributes.c
+daemon/gvfsjobqueryfsinfo.c
+daemon/gvfsjobqueryinfo.c
+daemon/gvfsjobqueryinforead.c
+daemon/gvfsjobqueryinfowrite.c
+daemon/gvfsjobread.c
+daemon/gvfsjobseekread.c
+daemon/gvfsjobseekwrite.c
+daemon/gvfsjobsetattribute.c
+daemon/gvfsjobsetdisplayname.c
+daemon/gvfsjobtrash.c
+daemon/gvfsjobunmount.c
+daemon/gvfsjobunmountmountable.c
+daemon/gvfsjobwrite.c
+daemon/main.c
+daemon/mount.c
+monitor/gphoto2/ggphoto2volume.c
+monitor/gphoto2/ggphoto2volumemonitor.c
+monitor/gphoto2/hal-utils.c
+monitor/hal/ghaldrive.c
+monitor/hal/ghalmount.c
+monitor/hal/ghalvolume.c
+monitor/hal/ghalvolumemonitor.c
+monitor/hal/hal-utils.c
+monitor/proxy/gproxydrive.c
+monitor/proxy/gproxymount.c
+monitor/proxy/gproxyvolume.c
+programs/gvfs-cat.c
+programs/gvfs-copy.c
+programs/gvfs-info.c
+programs/gvfs-ls.c
+programs/gvfs-mkdir.c
+programs/gvfs-move.c
+programs/gvfs-open.c
+programs/gvfs-save.c
+programs/gvfs-tree.c
diff --git a/trunk/po/ar.po b/trunk/po/ar.po
new file mode 100644
index 00000000..8bf4965d
--- /dev/null
+++ b/trunk/po/ar.po
@@ -0,0 +1,1586 @@
+# translation of gvfs.HEAD.po to Arabic
+# Copyright (C) 2008 THE gnome'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gnome package.
+#
+#
+# Djihed Afifi <djihed@gmail.com> 2008.
+# Khaled Hosny <khaledhosny@eglug.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-14 11:09+0100\n"
+"PO-Revision-Date: 2008-05-22 19:21+0300\n"
+"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
+"Language-Team: Arabic <doc@arabeyes.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Arabic\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "العملية غير مدعومة، ملفات على نقاط وصْل مختلفة"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "قيمة مرتجعة غير صحيحة من get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "قيمة مرتجعة غير صحيحة من query_info"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "تعذر جلب واصِف ملف الدفْق"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+msgid "Invalid return value from open"
+msgstr "قيمة غير صحيحة للدفْق من \"افتح\""
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+msgid "Didn't get stream file descriptor"
+msgstr "لم أحصل على واصِف ملف الدفْق"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "قيمة مُرتجعة غير صحيحة من النداء"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "قيمة مُرتجعة غير صحيحة من get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "تعذّر العثور على نقطة الضم الحاوية"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "اسم ملف غير صالح %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "قيمة مُرتجعة غير صحيحة من query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "قيمة مُرتجعة غير صحيحة من monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "قيمة مُرتجعة غير صحيحة من monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "خطأ في برتوكول الدفْق: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "نهاية الدفْق"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "أُلغيت العملية"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "لا يُدعم الالتماس على الدفْق"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "لا تُدعم عملية استعلام المعلومات"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, fuzzy, c-format
+msgid "Query info not supported on stream"
+msgstr "لا يُدعم الالتماس على الدفْق"
+
+#: ../client/gdaemonvfs.c:757
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "خطأ أثناء جلب معلومات الوصْل: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "خطأ أثناء الاتصال بالخادوم: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "خطأ أثناء إنشاء المقبس: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "خطأ أثناء الاتصال بالمقبس: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "تنسيق ملف معلومات غير صحيح."
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "محتوى قائمة خواص غير صحيح"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "خطأ أثناء الاتصال بـ D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "خدمة نظام ملفات %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "خطأ: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "الاستخدام: ‪%s --spawner dbus-id object_path‬"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "الاستخدام: ‪%s key=value key=value ...‬"
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "لم يُحدّد نوع الوصْل"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "نقطة الوصل %s تعمل مسبقا"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "خطأ أثناء بدأ جني الوصْل"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ على %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "لم يحدّد اسم مستضيف"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr "وصف وصْل خطأ"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "الملف غير موجود"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "الملف ليس مُجلّدا"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "اكتب"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "تعذّر إنشاء المجلد المؤقت"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, c-format
+msgid "No such file or directory"
+msgstr "ليس ثمّة ملف أو مجلد"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "الدليل غير فارغ"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "لا يمكن نسخ ملف على مجلد"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "منشئ الاسطوانات/ديڤيدي"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "الملف موجود"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobpull.c:173 ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135 ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149 ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119 ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150 ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122 ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "لا تدعم الخلفية هذا العملية"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "ليس ثمّة ملف أو مجلد في المسار المقصود"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "لا يمكن نسخ دليل على دليل"
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "الملف الهدف موجود مسبّقا"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "تعذّر النسخ التتابعي للدليل "
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr "ليس مدعومًا"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1403
+#, fuzzy
+msgid "Cannot connect to the system bus"
+msgstr "تعذّر الاتصال بالمستضيف"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Cannot initialize libhal"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "لم يحدّد أي مشغّل"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "تعذّر إيجاد المُشغّل %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "لا يحتوي المشغل %s على ملفات صوت"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "نقطة تحميل cdda2 على %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "قرص صوتي"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "نظام الملفات مشغول: لا ملفات مفتوحة"
+msgstr[1] "نظام الملفات مشغول: ملف واحد مفتوح"
+msgstr[2] "نظام الملفات مشغول: ملفين مفتوحين"
+msgstr[3] "نظام الملفات مشغول: %Id ملفات مفتوحة"
+msgstr[4] "نظام الملفات مشغول: %Id ملفا مفتوحا"
+msgstr[5] "نظام الملفات مشغول: %Id ملف مفتوح"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ليس ثمّة ملف %s على المشغّل %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "خطأ من 'paranoia' على المشغّل %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "خطأ أثناء الالتماس في الدفق على المشغّل %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr "ليس ثمّة ملف"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "الملف غير موجود أو ليس مقطعا صوتيا"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "خدمة نظام ملفات أقراص الصوت"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "الحاسوب"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "نظام الملفات"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678 ../daemon/gvfsbackendtrash.c:1786
+msgid "Can't open directory"
+msgstr "تعذّر فتح الدّليل"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "تعذّر فتح الملف القابل للوصْل"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "خطأ داخلي: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "تعذّر وصْل الملف"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "لا وسائط في القرص"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "لا ملف قابل للوصْل"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "تعذّر فصْل الملف"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "تعذّر إخراج الملف"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "خطأ HTTP‬: ‫%s‪"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "تعذّر تحليل الاستجابة"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "استجابة خالية"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "ردّ غير متوقّع من الخادوم"
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr "رد غير سليم"
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr "مشاركة WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr "أدخل كلمة سر %s"
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr "رجاءً أدخل كلمة سر الوسيط"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr "ليس مشاركة WebDAV مفعّلة"
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV على %s"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr "تعذّر إنشاء الطلب"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr "الملف الهدف موجود مسبقًا"
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr "عُدّل الملف خارجيّا"
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr "فشل إنشاء الملف الاحتياطي"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "لا يمكن مراقبة الملف أو الدليل"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "الشبكة"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "الحسابات غير مدعومة"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "قطع الخادوم الاتصال"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "لا يمكن فتح اتصال. هل هناك حائط ناري؟"
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "أُغلق اتصال البيانات"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "فشلت العمليّة"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "لا توجد مساحة كافية على الخادوم"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "عمليّة غير مدعومة"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "رُفض التّصريح"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "نوع الصّفحة غير معروف"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "اسم ملف غير صالح"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "رد غير صالح"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "إرسال معطّل"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "تعذّر الاتصال بالمستضيف"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "رجاء أدخل كلمة سر آف تي بي (ftp) على %s"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "أُلغِي حوار كلمة السر"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "آف تي بي (ftp) على %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "آف تي بي (ftp) باسم %s على %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "الملف دليل"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "النسخ الاحتياطية غير مدعومة"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "اسم الملف طويل جدًا"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "اسم الملف الهدف غير سليم"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, fuzzy, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "‏%s: %s: خطأ في فتح الملف: %s\n"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, fuzzy, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "ليس ثمّة ملف أو مجلد"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, fuzzy, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "اسم ملف غير صالح"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, fuzzy, c-format
+msgid "%s: %d: Not Supported"
+msgstr "ليس مدعومًا"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "آلة تصوير رقميّة (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "آلة تصوير %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "مشغل صوت %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "آلة تصوير"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "مشغل الصوت"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+#, fuzzy
+msgid "Failed to get folder list"
+msgstr "الملف غير موجود"
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+#, fuzzy
+msgid "No device specified"
+msgstr "لم يحدّد أي مشغّل"
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+#, fuzzy
+msgid "Error creating camera"
+msgstr "خطأ أثناء إنشاء المقبس: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+#, fuzzy
+msgid "Error loading device information"
+msgstr "حدث خطأ أثناء إرسال fd: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+#, fuzzy
+msgid "Error getting device information"
+msgstr "خطأ في إزالة الملف الهدف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+#, fuzzy
+msgid "Error setting up camera communications port"
+msgstr "خطأ أثناء جلب معلومات الوصْل: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "نقطة وصْل gphoto2 على %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+#, fuzzy
+msgid "No camera specified"
+msgstr "لم يحدّد اسم مستضيف"
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+#, fuzzy
+msgid "Error creating file object"
+msgstr "خطأ في إنشاء الملف الاحتياطي: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+#, fuzzy
+msgid "Error getting file"
+msgstr "خطأ أثناء حذف الملف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+#, fuzzy
+msgid "Error getting data from file"
+msgstr "خطأ في إزالة الملف الهدف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, fuzzy, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "خطأ أثناء الالتماس في الدفق على المشغّل %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "ليس دليلا"
+
+#: ../daemon/gvfsbackendgphoto2.c:2080
+#, fuzzy
+msgid "Failed to get file list"
+msgstr "الملف غير موجود"
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+#, fuzzy
+msgid "Error creating directory"
+msgstr "خطأ أثناء إنشاء المقبس: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+#, fuzzy
+msgid "Name already exists"
+msgstr "الملف الهدف موجود مسبقًا"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+#, fuzzy
+msgid "New name too long"
+msgstr "اسم الملف طويل جدًا"
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+#, fuzzy
+msgid "Error renaming dir"
+msgstr "حدث خطأ أثناء إرسال fd: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+#, fuzzy
+msgid "Error renaming file"
+msgstr "خطأ أثناء نقل الملف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, fuzzy, c-format
+msgid "Directory '%s' is not empty"
+msgstr "الدليل غير فارغ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, fuzzy
+msgid "Error deleting directory"
+msgstr "خطأ أثناء حذف الملف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+#, fuzzy
+msgid "Error deleting file"
+msgstr "خطأ أثناء حذف الملف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+#, fuzzy
+msgid "Can't write to directory"
+msgstr "تعذّر فتح الدّليل"
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+#, fuzzy
+msgid "Error writing file"
+msgstr "خطأ أثناء حذف الملف: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+#, fuzzy
+msgid "Not supported (not same directory)"
+msgstr "ليس دليلا"
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "خطأ عميل ‪HTTP‬: ‫%s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ترميز غير سليم)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "تنبيه المجلد غير مدعوم"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "شبكة ويندوز"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "شبكة محليّة"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "مراقب أمكنة الشبكة"
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "‏%s على %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "خرج برنامج ssh بصورة غير متوقّعة"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "اسم المستضيف مجهول"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "لا توجيه للمستضيف"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "رفض الخادوم الاتصال"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "فشل التحقق من مفتاح المستضيف"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "فشل تشعيب برنامج ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "فشل تشعيب برنامج ‪ssh‬: ‫%s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "انتهت المهلة أثناء الولوج"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "أدخل عبارة سر المفتاح"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "أدخل كلمة السر"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "تعذّر إرسال كلمة السر"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "لُج على أي حال"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "ألغِ الولوج"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"هوية الحاسوب البعيد (%s) غير معروفة.\n"
+"يحدث هذا عند الولوج إلى حاسوب للمرّة الأولى.\n"
+"\n"
+"الهوية المرسلة من الحاسوب البعيد هي %s. إذا أردت التأكد من سلامة الاستمرار، "
+"اتصل بمدير النظام."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "أُلغِي حوار الولوج"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "لا يمكن إرسال تأكيد هوية الخادوم"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "خطأ بروتوكول"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "‏sftp على %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "تعذّر إيجاد أمر ssh مدعوم"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "فشل"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "تم استقبال رد غير صحيح"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "خطأ في إنشاء الملف الاحتياطي: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "تعذّر إنشاء الملف المؤقت"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr "لا يمكن نقل دليل على دليل"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "كلمة السر مطلوبة لمشاركة %s على %s"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "خطأ داخلي (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr "فشل وصْل مشاركة ويندوز"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr "نوع التماس غير مدعوم"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "فشل إنشاء ملف تخزين: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "خطأ أثناء حذف الملف: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "خطأ أثناء نقل الملف: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "خطأ في إزالة الملف الهدف: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr "تعذّر نقل المجلد تتابعيا"
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr "خادوم نظام ملفات مشاركات ويندوز"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "مشاركات ويندوز على %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "الملف ليس قابلا للوصل"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "ليس ملفا اعتياديا"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "خادوم نظام ملفات شبكة ويندوز"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "المهملات"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "‏%s (في المهملات)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "تعذّر حذف المهملات"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "تنبيه مجلد المهملات غير مدعوم"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "نوع خلفية غير سليم"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "حدث خطأ أثناء إرسال fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "لا تدعم الخلفية الوصلات الرمزية"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "رسالة dbus غير سليمة"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "استبدل الخادوم القديم."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "لا تبدأ fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "عفريت GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "عفريت GVFS الرئيسي"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "جرّب ‪\"%s --help\"‬ لمزيد من المعلومات."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "معطيات غير سليمة من الابن المُشعّب"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "فشل الفصْل: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "المكان المحدد ليس موصولا"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "المكان المحدد ليس مدعوما"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "المكان موصول من قبْل"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "المكان ليس قابلا للوصْل"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "اسطوانة"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "قارئ اسطوانات"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "ناسخ اسطوانات"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "مشغّل ‪%s/%s‬"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "مشغّل %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "مشغل أقراص مرنة"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "مُشغّل RAID برمجي"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "مشغل USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "مشغّل ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "مشغّل SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "مشغّل FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "قارئ أشرطة"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "مشغّل فلاش مضغوط"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "مشغل قلم ذاكرة"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "مشغّل SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "مشغّل SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "مشغّل Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "مشغل Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "مشغل قلم"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "مشغل تخزين عام"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "فشل إخراج الوسيط، واحد أو أكثر من الأجزاء على الوسيط مشغول."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%I.1f ك.بايت"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%I.1f م.بايت"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%I.1f ج.بايت"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "قرص صوت و بيانات مختلط"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "وسط %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s بيانات معمّاة"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "اسطوانة"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "اسطوانة فارغة"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "اسطوانة قراءة"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "اسطوانة قراءة فارغة"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "اسطوانة إعادة كتابة"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "اسطوانة إعادة كتابة فارغة"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "قرص DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "قرص DVD-RAM فارغ"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "قرص DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "قرص DVD-RAM فارغ"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "قرص DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "قرص DVD-RW فارغ"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "قرص DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "قرص DVD+R فارغ"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "قرص DVD+RW فارغ"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "قرص DVD+RW فارغ"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "قرص DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "قرص DVD-RAM فارغ"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "قرص Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "قرص Blu-Ray فارغ"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "قرص Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "قرص Blu-Ray R فارغ"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "قرص Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "قرص Blu-Ray RW فارغ"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "قرص HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "قرص HD DVD فارغ"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "قرص HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "قرص HD DVD-R فارغ"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "قرص HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "قرص HD DVD-RW فارغ"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "قرص MO"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "قرص MO فارغ"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "قرص"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "قرص فارغ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "‏%s: %s: خطأ في فتح الملف: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "‏%s: %s، خطأ في الكتابة إلى الخرج اقياسي"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "‏%s: %s، خطأ في قراءة: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "‏%s: %s: خطأ في غلق: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "أماكن... - جمّع الأماكن إلى الخرج القياسي"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"جمّع الملفات في الأماكن واطبعهم إلى الخرج القياسي. يعمل كأدات cat التقليدية، "
+"لكن باستخدام أماكن gvfs بدلا من الملفات المحلية. مثلا يمكنك استخدام شيء مثل "
+"smb://server/resource/file.txt كمكان لتجميعه."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"ملاحظة: مرر إلى cat إذا كانت تريد خياراته التنسيقية مثل ‪-n‬، ‪-T‬، أو غيرها."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "‏%s: لا أماكن"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "‏%s: %s: خطأ أثناء فتح المكان: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "‏%s: %s: خطأ أثناء بدأ التطبيق: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ملف... - افتح الملفات بالبرنامج المسجل"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"افتح الملف/الملفات بالبرنامج المبدئي المسجل لمعالجة هذا النوع من الملفات."
+
+#, fuzzy
+#~ msgid "Error creating port info list"
+#~ msgstr "خطأ أثناء إنشاء المقبس: %s"
+
+#, fuzzy
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "خطأ أثناء جلب معلومات الوصْل: %s"
+
+#, fuzzy
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "نظام الملفات مشغول: لا ملفات مفتوحة"
+
+#, fuzzy
+#~ msgid "Error listing folders"
+#~ msgstr "خطأ أثناء حذف الملف: %s"
+
+#, fuzzy
+#~ msgid "Error listing files in folder"
+#~ msgstr "خطأ أثناء حذف الملف: %s"
+
+#~ msgid "File unavailable"
+#~ msgstr "ملفّ غير متوفّر"
diff --git a/trunk/po/as.po b/trunk/po/as.po
new file mode 100644
index 00000000..83e42e83
--- /dev/null
+++ b/trunk/po/as.po
@@ -0,0 +1,1645 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Amitakhya Phukan <aphukan@fedoraproject.org>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: as\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
+"cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-27 23:04+0000\n"
+"PO-Revision-Date: 2009-03-16 11:18+0530\n"
+"Last-Translator: Amitakhya Phukan <aphukan@fedoraproject.org>\n"
+"Language-Team: Assamese <fedora-trans-as@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 0.3\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "এই কৰ্ম অসমৰ্থিত, ফাইলগুলি আলাদা মাউন্টে অবস্থিত"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "স্ট্ৰিম ফাইলেৰ ডেস্ক্ৰিপ্টাৰ পাওয়া সম্ভব নহয়"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "স্ট্ৰিম ফাইলেৰ ডেস্ক্ৰিপ্টাৰ পাওয়া সম্ভব নহয়"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "এনক্লোজিং মাউন্ট খুঁজে পাওয়া যায়নি"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ফাইলেৰ নাম অবৈধ: %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfileenumerator.c:351
+#
+#: ../client/gdaemonfileinputstream.c:628
+#: ../client/gdaemonfileinputstream.c:781
+#: ../client/gdaemonfileinputstream.c:899
+#: ../client/gdaemonfileinputstream.c:1147
+#: ../client/gdaemonfileinputstream.c:1389
+#: ../client/gdaemonfileoutputstream.c:504
+#: ../client/gdaemonfileoutputstream.c:679
+#: ../client/gdaemonfileoutputstream.c:871
+#: ../client/gdaemonfileoutputstream.c:1050
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+msgid "Operation was cancelled"
+msgstr "কৰ্ম বাতিল কৰা হয়েছে"
+
+#: ../client/gdaemonfileinputstream.c:525
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1680
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:448
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1232
+#: ../client/gdaemonfileoutputstream.c:1242
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "স্ট্ৰিম প্ৰটোকল-এ ত্ৰুটি ঘটেছে: %s"
+
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1242
+msgid "End of stream"
+msgstr "স্ট্ৰিমেৰ শেষাংশ"
+
+#: ../client/gdaemonfileinputstream.c:1328
+#
+#: ../client/gdaemonfileoutputstream.c:979
+msgid "Seek not supported on stream"
+msgstr "স্ট্ৰিম দ্বাৰা Seek সমৰ্থিত হয় না"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "মাউন্টেৰ বৰ্ণনা প্ৰাপ্তিতে ত্ৰুটি: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "daemon-ৰ সাথে সংযোগে ত্ৰুটি:%s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read থেকে প্ৰাপ্ত মান সঠিক নয়"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "socket তৈৰি কৰতে ত্ৰুটি: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "socket-এ সংযোগ কৰতে ত্ৰুটি: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "ফাইলেৰ বৰ্ণনাৰ বিন্যাস সঠিক নয়"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "info list content বৈশিষ্ট্য সঠিক নয়"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi আৰম্ভ কৰতে সমস্যা: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi ৰিসোলভাৰ নিৰ্মাণ কৰতে সমস্যা: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" মীমাংসা কৰতে ত্ৰুটি, \"%s\" পৰিসেবা \"%s\" ডোমেইনে চলমান"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" মীমাংসা কৰতে ত্ৰুটি, \"%s\" পৰিসেবা \"%s\" ডোমেইনে চলমান। এক অথবা "
+"একাধিক TXT ৰেকৰ্ড অনুপস্থিত।আবশ্যক কি: \"%s\"।"
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" মীমাংসা কৰতে সময় উত্তীৰ্ণ হয়েছে, \"%s\" পৰিসেবা \"%s\" ডোমেইনে চলমান"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd encoded_triple '%s' ত্ৰুটিপূৰ্ণ"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon এনকোডিং-ৰ %d সংস্কৰণ ব্যবস্থাপনা কৰতে সক্ষম নয়"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon-ৰ ক্ষেত্ৰে ত্ৰুটিপূৰ্ণ ইনপুট তথ্য প্ৰদত্ত"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus-এ সংযোগ কৰতে ত্ৰুটি: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ফাইল-সিস্টেম পৰিসেবা"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ত্ৰুটি: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ব্যবহাৰেৰ নিয়ম: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Usage: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "মাউন্ট কৰতে ব্যবহৃত ধৰন চিহ্নিত কৰা নহয়"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s-ৰ মাউন্টপয়েন্ট বৰ্তমানে সক্ৰিয়"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "মাউন্ট daemon চালু কৰতে ত্ৰুটি ঘটেছে"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "/ %s-ৰ উপৰ"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "কোনো হোস্ট-ৰ নাম উল্লেখ কৰা নহয়"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "মাউন্ট বৰ্ণনা সঠিক নয়"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ফাইল অনুপস্থিত"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "এই ফাইলটি একটি ডিৰেক্টৰি নয়"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "বাৰ্ন কৰুন"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "অস্থায়ী ডিৰেক্টৰি প্ৰস্তুত কৰতে অক্ষম"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "এই নামে কোনো ফাইল বা ডিৰেক্টৰি নেই"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+#
+msgid "Directory not empty"
+msgstr "ডিৰেক্টৰি খালি নয়"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ডিৰেক্টৰিৰ উপৰ ফাইল কপি কৰা সম্ভব নয়"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD নিৰ্মাণ ব্যবস্থা"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "ফাইল উপস্থিত ৰয়েছে"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "এই কৰ্মটি ব্যাক-এন্ড দ্বাৰা সমৰ্থিত নয়"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "উদ্দিষ্ট পাথে এই নামে ফাইল বা ডিৰেক্টৰি উপস্থিত নেই"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+#
+msgid "Can't copy directory over directory"
+msgstr "ডিৰেক্টৰিৰ উপৰ ডিৰেক্টৰি কপি কৰা যায়নি"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "উদ্দিষ্ট ফাইল উপস্থিত ৰয়েছে"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+#
+msgid "Can't recursively copy directory"
+msgstr "ৰিকাৰ্সিভ ভাবে ডিৰেক্টৰি কপি কৰা যাবে না"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "সমৰ্থিত নয়"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "সিস্টেম বাসেৰ সাথে সংযোগ স্থাপনে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "libhal কনটেক্সট নিৰ্মাণ কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "libhal আৰম্ভ কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "কোনো ড্ৰাইভ চিহ্নিত কৰা নহয়"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ড্ৰাইভ খুঁজে পাওয়া যায়নি: %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ড্ৰাইভ %s-ৰ মধ্যে কোনো অডিও ফাইল নেই"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s-ৰ উপৰ cdda মাউন্ট"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "অডিও ডিস্ক"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ফাইল সিস্টেম ব্যস্ত: %d-টি ফাইল খোলা"
+msgstr[1] "ফাইল সিস্টেম ব্যস্ত: %d-টি ফাইল খোলা"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "%s নামক কোনো ফাইল, %s ড্ৰাইভেৰ মধ্যে উপস্থিত নেই"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ড্ৰাইভ %s এ 'paranoia' থেকে উৎপন্ন ত্ৰুটি"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ড্ৰাইভ %s-এ স্ট্ৰিম খুঁজতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "এই নামে ফাইল অনুপস্থিত"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "এই নামেৰ ফাইলটি হয় অনুপস্থিত অথবা অডিও ট্ৰ্যাক নয়"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "অডিও CD ফাইল-সিস্টেম পৰিসেবা"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+#
+msgid "Filesystem"
+msgstr "নথিপত্ৰপ্ৰণালী"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "ডিৰেক্টৰি খোলা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "মাউন্টযোগ্য ফাইল খোলা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "অভ্যন্তৰীণ ত্ৰুটি: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ফাইল মাউন্ট কৰা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ড্ৰাইভে কোনো মিডিয়া নেই"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "ফাইলটি মাউন্টযোগ্য নয়"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ফাইলটি আন-মাউন্ট কৰা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ফাইলটি বেৰ কৰা সম্ভব নয়"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ত্ৰুটি: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "প্ৰাপ্ত উত্তৰ পাৰ্স কৰা যায়নি"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "প্ৰাপ্ত উত্তৰ ফাঁকা"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "সাৰ্ভাৰ থেকে প্ৰাপ্ত উত্তৰ প্ৰত্যাশিত হয়"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "প্ৰাপ্ত উত্তৰ বৈধ নয়"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV শেয়াৰ"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s-ৰ জন্য পাসওয়াৰ্ড লিখুন"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "প্ৰক্সি-ৰ জন্য পাসওয়াৰ্ড লিখুন"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV সমৰ্থিত শেয়াৰ নয়"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s-ৰ উপৰ WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "অনুৰোধ তৈৰি কৰা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "উল্লিখিত ফাইল বৰ্তমানে উপস্থিত"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "ফাইলটি স্বতন্ত্ৰৰূপে পৰিবৰ্তন কৰা হয়েছে"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "ব্যাক-আপ ফাইল নিৰ্মাণ কৰতে ব্যৰ্থ"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "স্থানীয় নেটওয়াৰ্ক"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ফাইল বা ডিৰেক্টৰি নিৰীক্ষণ কৰা সম্ভব নহয়"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "নেটৱৰ্ক"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "অ্যাকাউন্ট সমৰ্থিত নয়"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "হোস্ট সংযোগ বন্ধ কৰেছে"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "তথ্য সংযোগ তৈৰি সম্ভব নহয়। সম্ভবত ফায়াৰওয়াল দ্বাৰা এটি প্ৰতিৰোধ কৰা হচ্ছে?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "তথ্য সংযোগ বন্ধ কৰা হয়েছে"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "কৰ্ম বিফল"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "সাৰ্ভাৰে কোনো অবশিষ্ট স্থান নেই"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "এই কৰ্মটি অসমৰ্থিত"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+#
+msgid "Permission denied"
+msgstr "অনুমতি প্ৰদান কৰা নহয়"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "অজানা পেজ প্ৰকাৰ"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+#
+msgid "Invalid filename"
+msgstr "অবৈধ ফাইলেৰ নাম"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "উত্তৰ বৈধ নয়"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "বিচ্ছিন্ন সংযোগ"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "হোস্টেৰ সাথে সংযোগ স্থাপনে ব্যৰ্থ"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "%s ৰূপে %s-ৰ উপৰ ftp-ৰ জন্য পাসওয়াৰ্ড লিখুন"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s-ৰ উপৰ ftp-ৰ জন্য পাসওয়াৰ্ড লিখুন"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "পাসওয়াৰ্ড ডায়লগ বন্ধ কৰা হয়েছে"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s-ৰ উপৰ ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp as %s on %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "চিহ্নিত ফাইলটি ডিৰেক্টৰি"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "ব্যাক আপেৰ জন্য সমৰ্থন অনুপস্থিত"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ফাইলেৰ নাম অত্যাধিক লম্বা"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "উদ্দিষ্ট ফাইলেৰ নাম সঠিক নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ডিৰেক্টৰি অথবা ফাইল উপস্থিত ৰয়েছে"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: এই নামে কোনো ফাইল বা ডিৰেক্টৰি নেই"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ফাইলেৰ নাম বৈধ নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: সমৰ্থিত নয়"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ডিজিটাল ক্যামেৰা (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s ক্যামেৰা"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s অডিও প্লেয়াৰ"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+#
+msgid "Camera"
+msgstr "ক্যামেৰা"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "অডিও প্লেয়াৰ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "কোনো ডিভাইস চিহ্নিত কৰা নহয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 কনটেক্সট নিৰ্মাণ কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "ক্যামেৰা তৈৰি কৰতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "ডিভাইস সংক্ৰান্ত তথ্য লোড কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "ডিভাইস সংক্ৰান্ত তথ্য অনুসন্ধান কৰতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "ডিভাইস সংক্ৰান্ত ত্ৰুটি প্ৰাপ্ত কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "ক্যামেৰাৰ সাথে সংযোগকাৰী পোৰ্ট নিৰ্ধাৰণ কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "ক্যামেৰা আৰম্ভ কৰতে ব্যৰ্থ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s-তে gphoto2 মাউন্ট কৰা হয়েছে"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "কোনো ক্যামেৰা উল্লেখ কৰা নহয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "ফাইল অবজেক্ট তৈৰি কৰতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "ফাইল প্ৰাপ্ত কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "ফাইল থেকে তথ্য প্ৰাপ্ত কৰতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "আইকন নিৰ্দেশক '%s' ত্ৰুটিপূৰ্ণ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "ক্যামেৰা %s-ৰ মধ্যে স্ট্ৰিম seek কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+#
+msgid "Not a directory"
+msgstr "ডিৰেক্টৰি নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "ফোল্ডাৰ তালিকা প্ৰাপ্ত কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "ফাইলেৰ তালিকা প্ৰাপ্ত কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "ডিৰেক্টৰি নিৰ্মাণ কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "উল্লিখিত নাম বৰ্তমানে উপস্থিত"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "নতুন নাম অত্যাধিক লম্বা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "ডিৰেক্টৰিৰ নাম পৰিবৰ্তন কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "ফাইলেৰ নাম পৰিবৰ্তন কৰতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "ডিৰেক্টৰি '%s' ফাঁকা নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "ডিৰেক্টৰি মুছে ফেলতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "ফাইল মুছে ফেলতে ত্ৰুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "ডিৰেক্টৰিৰ মধ্যে লেখা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "সংযোজন কৰাৰ উদ্দেশ্যে নতুন ফাইল বৰাদ্দ কৰা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "সংযোজন কৰাৰ উদ্দেশ্যে চিহ্নিত ফাইল পড়তে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "সংযোজন কৰাৰ উদ্দেশ্যে চিহ্নিত ফাইলেৰ তথ্য প্ৰাপ্ত কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "ফাইলে লিখতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "সমৰ্থিত নয় (এক ডিৰেক্টৰি নয়)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Not supported (src is dir, dst is dir)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "সমৰ্থিত নয় (src একটি ডিৰেক্টৰি, dst একটি উপস্থিত ফাইল)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "সমৰ্থিত নয় (src একটি ফাইল, dst একটি ডিৰেক্টৰি)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP Client ত্ৰুটি: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (এনকোডিং সঠিক নয়)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ডিৰেক্টৰি সংক্ৰান্ত সুচনাপ্ৰদান ব্যবস্থা বৰ্তমানে সমৰ্থিত নয়"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+#
+msgid "Windows Network"
+msgstr "Windows নেটওয়াৰ্ক"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Network Location Monitor"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s, %s-ৰ উপৰ"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB সমৰ্থন উপলব্ধ নয়। অনুগ্ৰহ কৰে আপনাৰ সফ্টওয়্যাৰ বিক্ৰেতাৰ সাথে যোগাযোগ কৰুন"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "ডিভাইসেৰ সাথে সংযোগ বিচ্ছিন্ন হয়েছে"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "ডিভাইস দ্বাৰা প্ৰয়োগকাৰী সফ্টওয়্যাৰ আপডেট কৰা আবশ্যক"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh প্ৰোগ্ৰাম অপ্ৰত্যাশিতভাবে বন্ধ হয়ে গেছে"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "হোস্টেৰ নাম অজ্ঞাত"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "হোস্টেৰ সাথে সংযোগেৰ পথ পাওয়া যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "সাৰ্ভাৰ সংযোগ প্ৰত্যাখ্যান কৰেছে"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "হোস্ট-কি যাচাই কৰা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh প্ৰোগ্ৰাম তৈৰি কৰা যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh প্ৰোগ্ৰাম তৈৰি কৰা যায়নি: %s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr "লগ-ইন কৰাৰ সময়সীমাৰ মেয়াদ উত্তীৰ্ণ হয়েছে"
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr "কি-ৰ জন্য পাসফ্ৰেজ লিখুন"
+
+#: ../daemon/gvfsbackendsftp.c:857
+#
+msgid "Enter password"
+msgstr "পাসওয়াৰ্ড লিখুন"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "পাসওয়াৰ্ড পাঠানো সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "তথাপি লগ-ইন কৰা হবে"
+
+#: ../daemon/gvfsbackendsftp.c:926
+#
+msgid "Cancel Login"
+msgstr "লগ-ইন বাতিল কৰুন"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"দূৰবৰ্তী কম্পিউটাৰ (%s) এৰ পৰিচয় অজানা।\n"
+"কম্পিউটাৰে প্ৰথমবাৰ লগ-ইন কৰলে এটি স্বাভাবিক।\n"
+"\n"
+"%s-টি দূৰবৰ্তী কম্পিউটাৰেৰ পৰিচিতি। আপনি যদি নিশ্চিত হতে চান তাহলে সিস্টেম "
+"অ্যাডমিনিস্ট্ৰেটাৰেৰ সাথে যোগাযোগ কৰুন।"
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "লগ-ইন ডায়লগ বন্ধ কৰা হয়েছে"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr "হোস্টেৰ পৰিচয়পত্ৰ প্ৰদান কৰা সম্ভব নহয়"
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+#
+msgid "Protocol error"
+msgstr "প্ৰোটোকল সংক্ৰান্ত ত্ৰুটি"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "%s-ৰ জন্য %s-এ sftp কৰুন"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "%s-ৰ উপৰ sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr "সমৰ্থিত ssh কম্যান্ড খুঁজে পাওয়া যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "বিফলতা"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "প্ৰাপ্ত উত্তৰ সঠিক নয়"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead-ৰ মধ্যে অবৈধ icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "ব্যাক-আপ ফাইল তৈৰি কৰতে ত্ৰুটি: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "অস্থায়ী ফাইল প্ৰস্তুত কৰতে অক্ষম"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+#
+msgid "Can't move directory over directory"
+msgstr "ডিৰেক্টৰিৰ উপৰ ডিৰেক্টৰি স্থানান্তৰ কৰা যাবে না"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s শেয়াৰ %s-ৰ উপৰ স্থাপিত এবং এই শেয়াৰটিৰ জন্য পাসওয়াৰ্ড প্ৰয়োজন"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "অভ্যন্তৰীণ ত্ৰুটি (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows শেয়াৰ মাউন্ট কৰতে অক্ষম"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "seek-ৰ ধৰন সমৰ্থিত নয়"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "ব্যাক-আপ ফাইল প্ৰস্তুত কৰা যায়নি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ফাইল মুছে ফেলতে ত্ৰুটি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ফাইল স্থানান্তৰ কৰতে সমস্যা: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "উদ্দিষ্ট ফাইল মুছে ফেলতে সমস্যা: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "ৰিকাৰ্সিভ ৰূপে ডিৰেক্টৰটি স্থানান্তৰ কৰা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows Shares Filesystem Service"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s-ৰ জন্য পাসওয়াৰ্ড প্ৰয়োজন"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s-এ Windows শেয়াৰসমূহ"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "সাৰ্ভাৰ থেকে শেয়াৰেৰ তালিকা প্ৰাপ্ত কৰতে ব্যৰ্থ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "এই ফাইলটি মাউন্ট কৰা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+#
+msgid "Not a regular file"
+msgstr "সাধাৰণ ফাইল নয়"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows Network Filesystem Service"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "আবৰ্জনাৰ ফোল্ডাৰ মুছে ফেলা নাও হতে পাৰে"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "আবৰ্জনাৰ বাক্সে উপস্থিত বস্তু পৰিবৰ্তন কৰা সম্ভব না হতে পাৰে"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+#
+msgid "Trash"
+msgstr "আৰ্বজনা"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "চিহ্নিত ব্যাক-এন্ড প্ৰকাৰ অসমৰ্থিত"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd প্ৰদানে ত্ৰুটি: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "ব্যাক-এন্ড symlink সমৰ্থন কৰে না"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "dbus সংবাদ সঠিক নয়"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "পুৰানো daemon-কে পৰিবৰ্তন কৰুন"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "fuse চালু কৰা হবে না।"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Daemon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS-ৰ প্ৰধান daemon"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%1$s: %2$s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "অধিক তথ্যেৰ জন্য \"%s --help\" ব্যবহাৰ কৰুন"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "spawn কৰা চাইল্ড থেকে প্ৰাপ্ত আৰ্গুমেন্টগুলি বৈধ নয়"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount কৰা যায়নি: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "নিৰ্দিষ্ট স্থান মাউন্ট কৰা নহয়"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "নিৰ্দিষ্ট স্থানটি সমৰ্থিত নয়"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "স্থানটি বৰ্তমানে মাউন্ট কৰা হয়েছে"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "স্থানটি মাউন্ট কৰা যাবে না"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ফাঁকা CD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ফাঁকা CD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ফাঁকা CD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ফাঁকা DVD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ফাঁকা DVD-RAM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ফাঁকা DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ফাঁকা DVD+R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ফাঁকা DVD+RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ফাঁকা DVD+R DL ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ফাঁকা Blu-Ray ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ফাঁকা Blu-Ray R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ফাঁকা Blu-Ray RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ফাঁকা HD DVD ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ফাঁকা HD DVD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ফাঁকা HD DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ফাঁকা MO ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ফাঁকা ডিস্ক"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ড্ৰাইভ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ফ্লপি ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "সফ্টওয়্যাৰ RAID ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "টেপ ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:210
+#
+msgid "Zip Drive"
+msgstr "Zip ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "বৃহৎ মাপে সংৰক্ষণেৰ ড্ৰাইভ"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "মিডিয়াতে একাধিক ভলিউম ব্যস্ত; মিডিয়া বেৰ কৰা যায়নি"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f মেগাবাইট"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f গিগাবাইট"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "অডিও/তথ্য সংমিশ্ৰিত ডিস্ক"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s মিডিয়া"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s এনক্ৰিপ্ট কৰা তথ্য"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ফাইল খুলতে ত্ৰুটি: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout এ লিখতে ত্ৰুটি"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: পাঠ কৰতে ত্ৰুটি: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:বন্ধ কৰতে ত্ৰুটি: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - concatenate LOCATIONS to standard output."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: অবস্থান অনুপস্থিত"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: চিহ্নিত অবস্থান খুলতে ত্ৰুটি: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: অ্যাপ্লিকেশন আৰম্ভ কৰতে ত্ৰুটি: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - open FILES with registered application."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+
+
diff --git a/trunk/po/be@latin.po b/trunk/po/be@latin.po
new file mode 100644
index 00000000..6afdf744
--- /dev/null
+++ b/trunk/po/be@latin.po
@@ -0,0 +1,1681 @@
+# Biełaruski pierakład gvfs.
+# Copyright (C) 2008 Ihar Hrachyshka
+# This file is distributed under the same license as the gvfs package.
+# Ihar Hrachyshka <booxter@lacinka.org>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-18 01:50+0200\n"
+"PO-Revision-Date: 2009-02-18 01:58+0200\n"
+"Last-Translator: Ihar Hrachyshka <booxter@lacinka.org>\n"
+"Language-Team: Belarusian Latin <i18n@mova.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"Aperacyja nie padtrymlivajecca, bo fajły mieściacca na roznych zmantavanych "
+"fajłavych drevach"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Niapravilnaja viernutaja vartaść ad get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Niapravilnaja viernutaja vartaść ad query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Niemahčyma atrymać deskryptara strumienievaha fajłu"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Niapravilnaja viernutaja vartaść ad open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Nie atrymany deskryptar strumienievaha fajłu"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Niapravilnaja viernutaja vartaść ad call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Niapravilnaja viernutaja vartaść ad get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Niemahčyma znajści kancavoha mantavańnia"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Niapravilnaja nazva fajłu %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Niapravilnaja viernutaja vartaść ad query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Niapravilnaja viernutaja vartaść ad monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Niapravilnaja viernutaja vartaść ad monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Aperacyja anulavanaja"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Pamyłka ŭ strumienievym pratakole: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Kaniec strumienia"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Pieraskok nie padtrymlivajecca dla strumienia"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Aperacyja zapytu źviestak nie padtrymlivajecca"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Atrymańnie źviestak pra zapyt nie padtrymlivajecca dla strumienia"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Pamyłka padčas atrymańnia źviestak ab mantavańni: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Pamyłka spałučeńnia z demanam: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Niapravilnaja viernutaja vartaść ad open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Pamyłka stvareńnia sokieta: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Pamyłka spałučeńnia z sokietam: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Niapravilny farmat źviestak ab fajle"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Niapravilnaje źmieściva śpisu sa źviestkami ab atrybutach"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Pamyłka inicyjalizacyi Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Pamyłka stvareńnia resolvera Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Pamyłka resolvavańnia słužby \"%s\" - \"%s\" - u damenie \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr "Pamyłka resolvavańnia słužby \"%s\" - \"%s\" - u damenie \"%s\". Nie staje prynamsi adnaho zapisu TXT. Patrebnyja klučy: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Skončyŭsia termin čakańnia dla resolvavańnia słužby \"%s\" - \"%s\" - u damenie \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Kiepski dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Nie ŭdałosia absłužyć versiju %d kadavańnia GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Kiepski ŭvachod dla GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Pamyłka spałučeńnia z D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Fajłavaja pasłuha %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Pamyłka: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Užyćcio: %s --spawner dbus-id ściežka_abjektu"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Užyćcio: %s kluč=vartaść kluč=vartaść ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Typ mantavańnia nie akreśleny"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "punkt mantavańnia dla %s užo vykarystoŭvajecca"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "pamyłka ŭklučeńnia demanu mantavańnia"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ na %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Nazva hostu nie akreślenaja"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Niapravilnaja specyfikacyja mantavańnia"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Fajł nie isnuje"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Fajł nie źjaŭlajecca kataloham"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Burn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Niemahčyma stvaryć časovy kataloh"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Niama takoha fajłu ci katalohu"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Kataloh nie pusty"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Niemahčyma skapijavać fajł na miesca katalohu"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Stvaralnik CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Fajł isnuje"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Aperacyja nie padtrymlivajecca ruchavikom"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "U metavaj ściežcy niama takoha fajłu ci katalohu"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Niemahčyma skapijavać kataloh na miesca inšaha katalohu"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Metavy fajł isnuje"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Niemahčyma rekursiŭna skapijavać kataloh"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Nie padtrymlivajecca"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Niemahčyma padłučycca da systemnaj šyny"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Niemahčyma stvaryć kantekst \"libhal\""
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Niemahčyma zinicyjalizavać \"libhal\""
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Pryvod nie akreśleny"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Niemahčyma znajści pryvod %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Pryvod %s nia ŭtrymlivaje hukavych fajłaŭ"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "zmantavańnie cdda na %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Hukavy dysk"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Fajłavaja systema zaniataja: %d adčynieny fajł"
+msgstr[1] "Fajłavaja systema zaniataja: %d adčynienyja fajły"
+msgstr[2] "Fajłavaja systema zaniataja: %d adčynienych fajłaŭ"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Niama fajłu %s u pryvodzie %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Pamyłka ad prahramy \"paranoia\" u pryvodzie %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Pamyłka pieraskoku ŭ strumieni ŭ pryvodzie %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Niama takoha fajłu"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Fajł nie isnuje albo nie źjaŭlajecca hukavoj ściežkaj"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Pasłuha fajłavaj systemy dla Audio CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Kamputar"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Fajłavaja systema"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Niemahčyma adčynić kataloh"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Niemahčyma adčynić mantavalny fajł"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Unutranaja pamyłka: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Niemahčyma zmantavać fajł"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "U pryvodzie niama nośbitu"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Nie mantavalny fajł"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Niemahčyma razmantavać fajł"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Niemahčyma vysunuć fajł"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Pamyłka HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Niemahčyma praanalizavać adkaz"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Pusty adkaz"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Niečakany adkaz ad servera"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Niapravilny adkaz"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Supolny resurs WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Uviadzi parol dla %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Uviadzi parol proxy"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Nie supolny resurs WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV na %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Niemahčyma stvaryć zapyt"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Metavy fajł užo isnuje"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Fajł byŭ źmienieny zvonku"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Nie ŭdałosia stvaryć zapasnuju kopiju fajłu"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lakalnaja sietka"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Niemahčyma nazirać za fajłam ci kataloham."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Sietka"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Konty nie padtrymlivajucca"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Kamputar začyniŭ spałučeńnie"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Niemahčyma adčynić spałučeńnie dla pieradačy źviestak. Mahčyma, hetamu "
+"zaminaje tvaja sietkavaja zasłona?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Spałučeńnie dla pieradačy źviestak začynienaje"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Niaŭdałaja aperacyja"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Na servery zakončyłasia volnaja prastora"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Aperacyja nie padtrymlivajecca"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Nie staje dazvołu"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Nieviadomy typ staronki"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Niapravilnaja nazva fajłu"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Niapravilny adkaz"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "złamanaja pieradača"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Niemahčyma spałučycca z kamputaram"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Uviadzi parol FTP dla %s na %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Uviadzi parol FTP dla %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Dyjaloh uvodu parolu anulavany"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp na %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp jak %s na %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "Fajł źjaŭlajecca kataloham"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "zapasnyja kopii jašče nie padtrymlivajucca"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nazva fajłu zadaŭhaja"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Niapravilnaja nazva metavaha fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Kataloh ci fajł isnuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Niama takoha fajłu ci katalohu"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Niapravilnaja nazva fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nie padtrymlivajecca"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Ličbavaja kamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Kamera u %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Hukavy player %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Hukavy player"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Pryłada nie akreślenaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Niemahčyma stvaryć kantekst \"gphoto2\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Pamyłka stvareńnia kamery"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Pamyłka zahruzki źviestak pra aparaturu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Pamyłka pošuku źviestak pra aparaturu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Pamyłka atrymańnia źviestak pra aparaturu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Pamyłka naładžvańnia źviaznaha portu kamery"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Pamyłka inicyjalizacyi kamery"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "zmantavańnie gphoto2 na %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Kamera nie akreślenaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Pamyłka stvareńnia fajłavaha abjekta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Pamyłka atrymańnia fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Pamyłka atrymańnia źviestak z fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Kiepski identyfikatar ikony \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Pamyłka pieraskoku ŭ strumieni z kamery %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Nie kataloh"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Nie ŭdałosia atrymać śpis katalohaŭ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Nie ŭdałosia atrymać śpis fajłaŭ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Pamyłka stvareńnia katalohu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Nazva ŭžo zaniataja"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Novaja nazva nadta daŭhaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Pamyłka źmieny nazvy katalohu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Pamyłka źmieny nazvy fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Kataloh \"%s\" nie pusty"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Pamyłka vydaleńnia katalohu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Pamyłka vydaleńnia fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Niemahčyma zapisać u katalohu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Niemahčyma vydzialić novy fajł, u jaki treba dadavać"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Niemahčyma pračytać z fajłu, u jaki treba dadavać"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Niemahčyma atrymać źviestki z fajłu, u jaki treba dadavać"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Pamyłka zapisu fajłu"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Nie padtrymlivajecca (inšy kataloh)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nie padtrymlivajecca (krynica-kataloh, meta-kataloh)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nie padtrymlivajecca (krynica-kataloh, meta-najaŭny fajł)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nie padtrymlivajecca (krynica-fajł, meta-kataloh)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Pamyłka klijenta HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (niapravilnaje kadavańnie)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Infarmavańnie dla katalohu nie padtrymlivajecca"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Sietka Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Sietkavy vandroŭnik"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s na %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Nie staje absłuhoŭvańnia USB. Źviarnisia da stavaralnikaŭ tvajho prahramnaha zabieśpiačeńnia."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Spałučeńnie z pryładaj stračanaje"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Pryłada vymahaje aktualizacyi prahramy"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Prahrama \"ssh\" niečakana vyjšła"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nieviadomaja nazva hostu"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Niama šlachu da hostu"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Server admoviŭ spałučeńniu"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Nie ŭdałosia spraŭdzić kluč hostu"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Niemahčyma ŭklučyć prahramu \"ssh\""
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Niemahčyma ŭklučyć prahramu \"ssh\": %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Skončyŭsia termin čakańnia ŭvachodu"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Uviadzi parol dla kluča"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Uviadzi parol"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Niemahčyma dasłać parol"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Usia adno ŭvajdzi"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Anuluj uvachod"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identyfikacyjnyja źviestki addalenaha kamputara (%s) nieviadomyja.\n"
+"Tak zdarajecca, kali ty ŭvachodziš na kamputar upieršyniu.\n"
+"\n"
+"Addaleny kamputar identyfikuje siabie jak %s. Kali ty chočaš całkam "
+"upeŭnicca ŭ biaśpiečnaści takoha spałučeńnia, spytaj pra heta ŭ systemnaha "
+"administratara."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Dyjaloh uvachodu anulavany"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Niemahčyma vysłać źviestki akreśleńnia hostu"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Pamyłka pratakołu"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, , c-format
+msgid "sftp for %s on %s"
+msgstr "SFTP dla %s na %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp na %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Niemahčyma znajści prydatnaha zahadu \"ssh\""
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Pamyłka"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Atrymany niapravilny adkaz"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Niapravilny icon_id '%s' u OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Pamyłka stvareńnia zapasnoj kopii fajłu: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Niemahčyma stvaryć časovy fajł"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Niemahčyma pieranieści kataloh na miesca inšaha katalohu"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Dla supolnaha resursu %s na %s vymahajecca parol"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Unutranaja pamyłka (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Nie ŭdałosia zmantavać supolny resurs Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Hety typ pieraskoku nie padtrymlivajecca"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Nie ŭdałosia stvaryć zapasnuju kopiju fajłu: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Pamyłka vydaleńnia fajłu: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Pamyłka pieranosu fajłu: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Pamyłka vydaleńnia metavaha fajłu: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Niemahčyma rekursiŭna pieranieści kataloh"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Pasłuha fajłavaj systemy dla supolnadastupnych resursaŭ Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Dla %s patrabujecca parol"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Supolnyja resursy Windows na %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Nie ŭdałosia atrymać śpis supolnych resursaŭ z servera"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Fajł nie mantavalny"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Niezvyčajny fajł"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Pasłuha fajłavaj systemy dla sietki Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Kataloh śmietnicy nielha vydalać"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Elementy ŭ śmietnicy nielha źmianiać"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Śmietnica"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Niapravilny typ ruchavika"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Pamyłka vysyłańnia fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symbalnyja poviazi nie padtrymlivajucca ruchavikom"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Niapravilnaje paviedamleńnie dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Padmiani staroha demana."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Nie ŭklučaj fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Deman GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hałoŭny deman GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Pasprabuj \"%s --help\" dla padrabiaźniejšych źviestak."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Niapravilnyja arhumenty dla stvoranaha pracesu-naščadka"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Nie ŭdałosia aŭtamatyčna zmantavać: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Akreślenaje pałažeńnie nie zmantavanaje"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Akreślenaje pałažeńnie nie padtrymlivajecca"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Pałažeńnie ŭžo zmantavanaje"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Niemahčyma zmantavać pałažeńnie"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Dysk CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Pusty dysk CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Dysk CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Pusty dysk CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Dysk CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Pusty dysk CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Dysk DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Pusty dysk DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Dysk DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Pusty dysk DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Dysk DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Pusty dysk DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Dysk DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Pusty dysk DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Dysk DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Pusty dysk DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Dysk DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Pusty dysk DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Dysk Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Pusty dysk Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Dysk Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Pusty dysk Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Dysk Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Pusty dysk Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Dysk HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Pusty dysk HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Dysk HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Pusty dysk HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Dysk HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Pusty dysk HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Dysk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Pusty dysk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Dysk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Pusty dysk"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Pryłada %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Pryłada %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Dyskietavod"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Pryłada Software RAID"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Pryłada USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Pryłada ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Pryłada SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Pryłada FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Stužkavaja pryłada"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Pryłada CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Pryłada MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Pryłada SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Pryłada SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Pryłada Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Pryłada Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Pryłada Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Pryłada Mass Storage"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Nie ŭdałosia vysunuć nośbit; adna ci niekalki partycyjaŭ z nośbita zaniatyja."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Dysk z hukam i źviestkami"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Nośbit u %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s zašyfravanych źviestak"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: pamyłka adčynieńnia fajłu: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, pamyłka zapisu ŭ standartnaje vyjście"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: pamyłka čytańnia: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: pamyłka začynieńnia: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "PAŁAŽEŃNIE... - spałučy PAŁAŽEŃNI na standartnym vyjści."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Spałučy fajły z pałažeńniaŭ i vyviedzi ich u standartnaje vyjście. Pracuje "
+"jak zvyčajnaja prahrama \"cat\", ale z pałažeńniami gvfs zamiest lakalnych "
+"fajłaŭ: napr., možna akreślić smb://server/resource/file.txt dla ŭłučeńnia."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Zaŭvaha: prosta kanvejeryzuj praz \"cat\", kali patrebnyja jaje opcyi "
+"farmatavańnia, napr., -n, -T dy inšyja."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: nie staje pałažeńniaŭ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: pamyłka adčynieńnia pałažeńnia: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: pamyłka ŭklučeńnia aplikacyi: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+"FAJŁY... - adčyniaj FAJŁY z dapamohaj zarehistravanych dla ich aplikacyj."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Adčyniaje fajł(y) z dapamohaj aplikacyj, zarehistravanych dla typaŭ fajłaŭ."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr ""
+#~ "Pamyłka prahladu katalohaŭ dziela vyznačeńnia prefiksu dla ihnaravańnia"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "Pamyłka stvareńnia śpisu sa źviestkami pra porty"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "Pamyłka atrymańnia źviestak pra port sa śpisu"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "Fajłavaja systema zaniataja: %d adčynienych fajłaŭ"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Pamyłka prahladu katalohaŭ"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "Pamyłka prahladu fajłaŭ z katalohu"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (u śmietnicy)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Niemahčyma vydalić śmietnicu"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Infarmavańnie dla śmietnicy nie padtrymlivajecca"
+
+#~ msgid "File unavailable"
+#~ msgstr "Fajłu niama"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Nośbit u %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Nośbit u %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Nośbit u %.1f GB"
+
+#~ msgid "File does not exist"
+#~ msgstr "Fajł nie isnuje"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Hukavy dysk u %s"
+
+#~ msgid "The file does not exist"
+#~ msgstr "Fajł nie isnuje"
diff --git a/trunk/po/bg.po b/trunk/po/bg.po
new file mode 100644
index 00000000..8927c363
--- /dev/null
+++ b/trunk/po/bg.po
@@ -0,0 +1,1635 @@
+# Bulgarian translation of gvfs po-file.
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+# Alexander Shopov <ash@contact.bg>, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs trunk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-11 11:20+0200\n"
+"PO-Revision-Date: 2009-02-11 11:19+0200\n"
+"Last-Translator: Alexander Shopov <ash@contact.bg>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"Действието не се поддържа, файловете са на различно монтирани местоположения"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Файловият дескриптор не може да бъде получен"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Файловият дескриптор не бе получен"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Извиканият модул върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info върна неправилна стойност"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Съдържащият монтиран обект не е открит"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Неправилно име на файл: %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir върна неправилна стойност"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file върна неправилна стойност"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Действието е отменено"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Грешка в поточния протокол: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Край на потока"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Потокът не поддържа търсене"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Запитващото действие не се поддържа"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Потокът не поддържа търсене"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Грешка при получаване на информация за файловата система: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Грешка при свързване към демон: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read върна неправилна стойност"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Грешка при създаване на гнездо: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Грешка при свързване към гнездо: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Неправилно форматирана информация за файл"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Неправилно съдържание на списък с информация за атрибути"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Грешка при инициализиране на Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Грешка при създаване на модула на Avahi за откриване по име: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"Грешка при откриването по име на услугата за „%s“ — „%s“ в домейна „%s“"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Грешка при откриването по име на услугата за „%s“ — „%s“ в домейна „%s“. "
+"Липсва поне един запис от вида „TXT“. Необходим ключ: „%s“."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"Изтече времето за откриването по име на услугата за „%s“ — „%s“ в домейна „%"
+"s“"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Неправилно кодирана тройка в dns-sd: „%s“"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Версия %d на кодирането GVfsIcon не се поддържа"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Неправилни входни данни за GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Грешка при свързване с D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Услуга за файловата система по %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Грешка: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Употреба: %s --spawner ид-dbus път_до_обект"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Употреба: %s ключ=стойност ключ=стойност…"
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Не е указан вид при монтирането"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "точката на монтиране на %s вече работи"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "грешка при стартирането на монтиращия демон"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ на %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Не е указано име на хост"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Неправилно указан обект за монтиране"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Файлът не съществува"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Файлът не е папка"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Записване"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Неуспех при създаване на временна папка"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Липсва такъв файл или папка"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Папката не е празна"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Файлът не може да бъде копиран върху папка"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Създаване на CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Файлът съществува"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Действието не се поддържа от модула"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "В целевия път липсва такъв файл или папка"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Папката не може да бъде копирана върху папка"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Целевият файл съществува"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Папката не може да бъде копирана рекурсивно"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Не се поддържа"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Не може да се направи връзка със системната шина"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Контекстът за libhal не може да бъде създаден"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Библиотеката libhal не може да бъде инициализирана"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Не е указано устройство"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Устройството %s не може да бъде открито"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Устройството %s не съдържа аудио файлове"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "монтиране по cdda в %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Аудио диск"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Файловата система е заета: отворен е %d файл"
+msgstr[1] "Файловата система е заета: отворени са %d файла"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Липсва файл %s на устройство %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Грешка от „paranoia“ от устройство %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Грешка при търсене в поток от устройство %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Няма такъв файл"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Файлът не съществува или не е аудио писта"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Услуга за файлова система на аудио CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Компютър"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Файлова система"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Папката не може да бъде отворена"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Файлът за монтиране не може да бъде отворен"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Вътрешна грешка: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Файлът не може да бъде монтиран"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "В устройството няма носител"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Не е файл за монтиране"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Файлът не може да бъде демонтиран"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Файлът не може да бъде изваден"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Грешка от HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Отговорът не може да бъде анализиран"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Празен отговор"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Неочакван отговор от сървъра"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Неправилен отговор"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Споделен ресурс по WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Въведете парола за %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Въведете паролата за сървъра-посредник"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Споделен ресурс без поддръжка на WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV на %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Заявката не може да бъде създадена"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Целевият файл вече съществува"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Файлът бе променен от външно приложение"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Резервният файл не бе създаден"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Локална мрежа"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Папката или файлът не могат да бъдат наблюдавани"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "DNS-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Мрежа"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Не се поддържат абонаменти"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Хостът затвори връзката"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Не може да се отвори връзка за данни. Възможно е да ви пречи защитната стена."
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Връзката за данни бе затворена"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Неуспешно действие"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Не е останало място на диска"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Действието не се поддържа"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Достъпът е отказан"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Неизвестен вид на страницата"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Неправилно име на файл"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Неправилен отговор"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "прекъснато предаване"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Не може да се направи връзка с хоста"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Въведете паролата за ftp на %s към %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Въведете паролата за ftp към %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Диалоговият прозорец за парола е отменен"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp към %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp като %s към %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Файлът е папка"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "резервни копия все още не се поддържат"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "името на файла е прекалено дълго"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Неправилно име на целевия файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Папката или файлът съществува"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Липсва такъв файл или папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Неправилно име на файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Не се поддържа"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Цифрова камера (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Камера от %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Аудио плеър от %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Аудио плеър"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Не е указано устройство"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Контекстът за gphoto2 не може да бъде създаден"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Грешка при създаване на камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Грешка при зареждане на информацията за устройството"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Грешка при проверка на информацията за устройството"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Грешка при получаването на информацията за устройството"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Грешка при настройването на порта за комуникация с камерата"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Грешка при инициализиране на камерата"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "монтиране по gphoto2 в %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Не е указана камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Грешка при създаване на файлов обект"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Грешка при получаване на файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Грешка при получаване на данни от файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Неправилен идентификатор на икона „%s“"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Грешка при търсене в поток от камера %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Не е папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Неуспех при получаването на съдържанието на папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Неуспех при получаването на списъка на файловете"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Грешка при създаване на папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Името вече съществува"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Новото име е прекалено дълго"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Грешка при преименуване на папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Грешка при преименуване на файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Папката „%s“ не е празна"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Грешка при изтриване на папка"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Грешка при изтриване на файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "В папката не може да се пише"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Не може да се задели новият файл, към който да се добавя"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Не може да се прочете файлът, към който да се добавя"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Не могат да се получат данните на файла, към който да се добавя"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Грешка при запис във файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Не се поддържа (не е същата папка)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Не се поддържа (изходът е папка, целта също)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Не се поддържа (изходът е папка, целта — съществуващ файл)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Не се поддържа (изходът е файл, целта — папка)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Клиентска грешка в HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (неправилно кодиране)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Известяването за папки не се поддържа"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Мрежа на Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Датчик за местоположения по мрежата"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s на %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Липсва поддръжка на USB. Свържете с с доставчика на софтуера"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Връзката с устройството е прекъсната"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Устройството изисква обновяване на софтуера"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Програмата за ssh неочаквано преустанови действие"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Неизвестно име на хост"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Няма маршрут до хост"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Сървърът отказа връзката"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Неуспешно потвърждаване на ключа на хоста"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Неуспех при пораждане на програма за ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Неуспех при пораждане на програма за ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Изтече времето за влизане в системата"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Въведете парола за ключа"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Въведете парола"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Паролата не може да бъде изпратена"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Влизане въпреки всичко"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Отмяна на влизането"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Идентичността на отдалечения компютър (%s) е непозната.\n"
+"Това се случва при първото свързване към отдалечен компютър.\n"
+"\n"
+"Той изпрати идентичността %s. Ако искате да сте напълно сигурни, че е "
+"безопасно да продължите, се свържете със системния администратор."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Диалоговият прозорец за влизане е отменен"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Информацията за идентичността на хоста не може да бъде изпратена"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Грешка в протокола"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp като %s към %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp към %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Не е открита поддържана команда за ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Неуспех"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Получен е неправилен отговор"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Неправилен идентификатор на икона — „%s“ в OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Грешка при създаване на резервно копие: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Неуспех при създаване на временен файл"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Папка не може да бъде преместена върху папка"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Необходима е парола за споделения ресурс %s на %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Вътрешна грешка (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Неуспех при монтирането на споделен ресурс на Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Неподдържан вид търсене"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Неуспех при създаване на резервен файл: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Грешка при изтриване на файл: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Грешка при преместване на файл: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Грешка при премахване на целевия файл: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Папка не може да бъде преместена рекурсивно върху папка"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Услуга за файлови системи на споделени ресурси на Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Необходима е парола за %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Споделени ресурси на Windows на %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Неуспех при получаването на споделените ресурси от сървъра"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Целевият файл не може да се монтира"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Не е обикновен файл"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Услуга за мрежова файлова система на Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Папката на кошчето не може да бъде изтрита"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Обектите в кошчето не могат да бъдат променяни"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Кошче"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Неправилен вид модул"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Грешка при изпращане на файловия дескриптор: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Символни връзки не се поддържат от модула"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Неправилно съобщение на D-BUS"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Замяна на стария демон."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Fuse да не се стартира"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Демон GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Основен демон за GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "За повече информация използвайте „%s --help“."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Неправилни аргументи от породения дъщерен процес"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Неуспешно автоматично монтиране: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Указаното местоположение не е монтирано"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Указаното местоположение не се поддържа"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Местоположението вече е монтирано"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Местоположението не може да се монтира"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Диск CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Празен диск CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Диск CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Празен диск CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Диск CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Празен диск CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Диск DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Празен диск DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Празен диск DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Празен диск DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Диск DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Празен диск DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Диск DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Празен диск DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Диск DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Празен диск DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Диск DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Празен диск DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Диск Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Празен диск Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Диск Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Празен диск Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Диск Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Празен диск Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Диск HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Празен диск HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Диск HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Празен диск HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Диск HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Празен диск HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Диск MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Празен диск MO"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Диск"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Празен диск"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HD DVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HD DVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HD DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Устройство %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Устройство %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Флопи устройство"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Устройство със софтуерен RAID"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Устройство с USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Устройство с ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Устройство със SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Устройство с FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Лентово устройство"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Устройство CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Устройство MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Устройство SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Устройство SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Устройство Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Устройство Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Устройство Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Устройство с огромен обем"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Неуспех при изваждането на носител. Поне един от томовете на носителя са "
+"заети."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Диск с аудио и данни"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Носител с обем %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Шифровани данни с обем %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: грешка при отваряне на файл: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s: грешка при запис към стандартния изход"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: грешка при четене: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: грешка при затваряне: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+"МЕСТОПОЛОЖЕНИЕ… — сливане на съдържанието на МЕСТОПОЛОЖЕНИЯТА към "
+"стандартния изход."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Сливане на файловете на местоположенията и отпечатване на стандартния изход. "
+"Работи подобно на стандартния инструмент „cat“, но се използват "
+"местоположения на gvfs вместо локални файлове, напр. можете да използвате "
+"местоположение като smb://сървър/ресурс/файл.txt за извеждане."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Бележка: подайте изхода от командата към „cat“, за да ползвате опциите на "
+"стандартния инструмент, напр. „-n“, „-T“ или др."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: не е дадено местоположение"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: грешка при отваряне на местоположение: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: грешка при стартиране на приложение: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ФАЙЛОВЕ… — отваряне на файлове с регистрираното за това приложение."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Отваряне на файла/овете със стандартното приложение регистрирано за този вид "
+"файлове."
diff --git a/trunk/po/bn_IN.po b/trunk/po/bn_IN.po
new file mode 100644
index 00000000..12d6b068
--- /dev/null
+++ b/trunk/po/bn_IN.po
@@ -0,0 +1,1657 @@
+# translation of bn_IN.po to Bengali INDIA
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Sankarshan Mukhopadhyay <sankarshan.mukhopadhyay@gmail.com>, 2008.
+# Runa Bhattacharjee <runab@redhat.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: bn_IN\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-27 15:51+0000\n"
+"PO-Revision-Date: 2009-03-10 16:24+0530\n"
+"Last-Translator: Runa Bhattacharjee <runab@redhat.com>\n"
+"Language-Team: Bengali INDIA <discuss@lists.ankur.org.in>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "এই কর্ম অসমর্থিত, ফাইলগুলি আলাদা মাউন্টে অবস্থিত"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "স্ট্রিম ফাইলের ডেস্ক্রিপ্টার পাওয়া সম্ভব হয়নি"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "স্ট্রিম ফাইলের ডেস্ক্রিপ্টার পাওয়া সম্ভব হয়নি"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info থেকে প্রাপ্ত মান সঠিক নয়"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "এনক্লোজিং মাউন্ট খুঁজে পাওয়া যায়নি"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ফাইলের নাম %s সঠিক নয়"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:628
+#: ../client/gdaemonfileinputstream.c:781
+#: ../client/gdaemonfileinputstream.c:899
+#: ../client/gdaemonfileinputstream.c:1147
+#: ../client/gdaemonfileinputstream.c:1389
+#: ../client/gdaemonfileoutputstream.c:504
+#: ../client/gdaemonfileoutputstream.c:679
+#: ../client/gdaemonfileoutputstream.c:871
+#: ../client/gdaemonfileoutputstream.c:1050
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+msgid "Operation was cancelled"
+msgstr "কর্ম বাতিল করা হয়েছে"
+
+#: ../client/gdaemonfileinputstream.c:525
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1680
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:448
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1232
+#: ../client/gdaemonfileoutputstream.c:1242
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "স্ট্রিম প্রটোকল-এ ত্রুটি ঘটেছে: %s"
+
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1242
+msgid "End of stream"
+msgstr "স্ট্রিমের শেষাংশ"
+
+#: ../client/gdaemonfileinputstream.c:1328
+#: ../client/gdaemonfileoutputstream.c:979
+msgid "Seek not supported on stream"
+msgstr "স্ট্রিমের ক্ষেত্রে seek কমান্ড সহযোগে খোঁজা সমর্থিত নয়"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "মাউন্টের বর্ণনা প্রাপ্তিতে ত্রুটি: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "daemon-র সাথে সংযোগে ত্রুটি:%s"
+
+#: ../client/gvfsiconloadable.c:145
+#| msgid "Invalid return value from get_info"
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read থেকে প্রাপ্ত মান সঠিক নয়"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "socket তৈরি করতে ত্রুটি: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "socket-এ সংযোগ করতে ত্রুটি: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "ফাইলের বর্ণনার বিন্যাস সঠিক নয়"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "info list content বৈশিষ্ট্য সঠিক নয়"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error deleting file: %s"
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi আরম্ভ করতে সমস্যা: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating socket: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi রিসোলভার নির্মাণ করতে সমস্যা: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" মীমাংসা করতে ত্রুটি, \"%s\" পরিসেবা \"%s\" ডোমেইনে চলমান"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" মীমাংসা করতে ত্রুটি, \"%s\" পরিসেবা \"%s\" ডোমেইনে চলমান। এক অথবা একাধিক TXT রেকর্ড অনুপস্থিত।"
+"আবশ্যক কি: \"%s\"।"
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" মীমাংসা করতে সময় উত্তীর্ণ হয়েছে, \"%s\" পরিসেবা \"%s\" ডোমেইনে চলমান"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd encoded_triple '%s' ত্রুটিপূর্ণ"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon এনকোডিং-র %d সংস্করণ ব্যবস্থাপনা করতে সক্ষম নয়"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon-র ক্ষেত্রে ত্রুটিপূর্ণ ইনপুট তথ্য প্রদত্ত"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus-এ সংযোগ করতে ত্রুটি: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ফাইল-সিস্টেম পরিসেবা"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ত্রুটি: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ব্যবহারের নিয়ম: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ব্যবহারের নিয়ম: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "মাউন্ট করতে ব্যবহৃত ধরন চিহ্নিত করা হয়নি"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s-র মাউন্টপয়েন্ট বর্তমানে সক্রিয়"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "মাউন্ট daemon চালু করতে ত্রুটি ঘটেছে"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "%s-র উপর / (root)"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "কোনো হোস্ট-র নাম উল্লেখ করা হয়নি"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "মাউন্ট বর্ণনা সঠিক নয়"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ফাইল অনুপস্থিত"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "এই ফাইলটি একটি ডিরেক্টরি নয়"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "বার্ন করুন"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "অস্থায়ী ডিরেক্টরি প্রস্তুত করতে অক্ষম"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "এই নামে কোনো ফাইল বা ডিরেক্টরি নেই"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "ডিরেক্টরি খালি নয়"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ডিরেক্টরির উপর ফাইল কপি করা সম্ভব নয়"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD নির্মাণ ব্যবস্থা"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "ফাইল উপস্থিত রয়েছে"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "এই কর্মটি ব্যাক-এন্ড দ্বারা সমর্থিত নয়"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "উদ্দিষ্ট পাথে এই নামে ফাইল বা ডিরেক্টরি উপস্থিত নেই"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "একটি ডিরেক্টরির উপরে অন্য ডিরেক্টরি কপি করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "উদ্দিষ্ট ফাইল উপস্থিত"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "ডিরেক্টরিকে রিকার্সিভ পদ্ধতিতে কপি করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "সমর্থিত নয়"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+#| msgid "Could not connect to host"
+msgid "Cannot connect to the system bus"
+msgstr "সিস্টেম বাসের সাথে সংযোগ স্থাপনে ব্যর্থ"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "libhal কনটেক্সট নির্মাণ করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "libhal আরম্ভ করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "কোনো ড্রাইভ চিহ্নিত করা হয়নি"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ড্রাইভ খুঁজে পাওয়া যায়নি: %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ড্রাইভ %s-র মধ্যে কোনো অডিও ফাইল নেই"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s-র উপর cdda মাউন্ট"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "অডিও ডিস্ক"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ফাইল সিস্টেম ব্যস্ত: %d-টি ফাইল খোলা"
+msgstr[1] "ফাইল সিস্টেম ব্যস্ত: %d-টি ফাইল খোলা"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "%s নামক কোনো ফাইল, %s ড্রাইভের মধ্যে উপস্থিত নেই"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ড্রাইভ %s এ 'paranoia' থেকে উৎপন্ন ত্রুটি"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ড্রাইভ %s-এ স্ট্রিম খুঁজতে ত্রুটি"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "এই নামে ফাইল অনুপস্থিত"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "এই নামের ফাইলটি হয় অনুপস্থিত অথবা অডিও ট্র্যাক নয়"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "অডিও CD ফাইল-সিস্টেম পরিসেবা"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "কম্পিউটার"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ফাইল-সিস্টেম"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "ডিরেক্টরি খোলা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "মাউন্টযোগ্য ফাইল খোলা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "অভ্যন্তরীণ ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ফাইল মাউন্ট করা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ড্রাইভে কোনো মিডিয়া নেই"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "ফাইলটি মাউন্টযোগ্য নয়"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ফাইলটি আন-মাউন্ট করা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ফাইলটি বের করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ত্রুটি: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "প্রাপ্ত উত্তর পার্স করা যায়নি"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "প্রাপ্ত উত্তর ফাঁকা"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "সার্ভার থেকে প্রাপ্ত উত্তর প্রত্যাশিত হয়"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "প্রাপ্ত উত্তর বৈধ নয়"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV শেয়ার"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s-র জন্য পাসওয়ার্ড লিখুন"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "প্রক্সি-র জন্য পাসওয়ার্ড লিখুন"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV সমর্থিত শেয়ার নয়"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+#| msgid "WebDAV share"
+msgid "WebDAV on %s"
+msgstr "%s-র উপর WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "অনুরোধ তৈরি করা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "উল্লিখিত ফাইল বর্তমানে উপস্থিত"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "ফাইলটি স্বতন্ত্ররূপে পরিবর্তন করা হয়েছে"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "ব্যাকআপ ফাইল তৈরি করা সম্ভব হয়নি"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "স্থানীয় নেটওয়ার্ক"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ফাইল বা ডিরেক্টরি নিরীক্ষণ করা সম্ভব হয়নি"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "নেটওয়ার্ক"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "অ্যাকাউন্ট সমর্থিত নয়"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "হোস্ট সংযোগ বন্ধ করেছে"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "তথ্য সংযোগ তৈরি সম্ভব হয়নি। সম্ভবত ফায়ারওয়াল দ্বারা এটি প্রতিরোধ করা হচ্ছে?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "তথ্য সংযোগ বন্ধ করা হয়েছে"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "কর্ম বিফল"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "সার্ভারে কোনো অবশিষ্ট স্থান নেই"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "এই কর্মটি অসমর্থিত"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "অনুমতি প্রাপ্ত হয়নি"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "অজানা পেজ প্রকার"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "ফাইলের নাম বৈধ নয়"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "উত্তর বৈধ নয়"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "বিচ্ছিন্ন সংযোগ"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "হোস্টের সাথে সংযোগ স্থাপনে ব্যর্থ"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+#| msgid "Enter password for ftp on %s"
+msgid "Enter password for ftp as %s on %s"
+msgstr "%s রূপে %s-র উপর ftp-র জন্য পাসওয়ার্ড লিখুন"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s-র উপর ftp-র জন্য পাসওয়ার্ড লিখুন"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "পাসওয়ার্ড ডায়লগ বন্ধ করা হয়েছে"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s-র উপর ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s নামে %s-তে ftp করুন"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "চিহ্নিত ফাইলটি ডিরেক্টরি"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "ব্যাক আপের জন্য সমর্থন অনুপস্থিত"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ফাইলের নাম অত্যাধিক লম্বা"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "উদ্দিষ্ট ফাইলের নাম সঠিক নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+#| msgid "%s: %s: error opening file: %s\n"
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ডিরেক্টরি অথবা ফাইল উপস্থিত রয়েছে"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+#| msgid "No such file or directory"
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: এই নামে কোনো ফাইল বা ডিরেক্টরি নেই"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+#| msgid "Invalid filename"
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ফাইলের নাম বৈধ নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+#| msgid "Not supported"
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: সমর্থিত নয়"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ডিজিটাল ক্যামেরা (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s ক্যামেরা"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s অডিও প্লেয়ার"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "ক্যামেরা"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "অডিও প্লেয়ার"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+#| msgid "No drive specified"
+msgid "No device specified"
+msgstr "কোনো ডিভাইস চিহ্নিত করা হয়নি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 কনটেক্সট নির্মাণ করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+#| msgid "Error creating socket: %s"
+msgid "Error creating camera"
+msgstr "ক্যামেরা তৈরি করতে ত্রুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "ডিভাইস সংক্রান্ত তথ্য লোড করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "ডিভাইস সংক্রান্ত তথ্য অনুসন্ধান করতে ত্রুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "ডিভাইস সংক্রান্ত ত্রুটি প্রাপ্ত করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "ক্যামেরার সাথে সংযোগকারী পোর্ট নির্ধারণ করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "ক্যামেরা আরম্ভ করতে ব্যর্থ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s-তে gphoto2 মাউন্ট করা হয়েছে"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+#| msgid "No hostname specified"
+msgid "No camera specified"
+msgstr "কোনো ক্যামেরা উল্লেখ করা হয়নি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+#| msgid "Error creating backup file: %s"
+msgid "Error creating file object"
+msgstr "ফাইল অবজেক্ট তৈরি করতে ত্রুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+#| msgid "Error deleting file: %s"
+msgid "Error getting file"
+msgstr "ফাইল প্রাপ্ত করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+#| msgid "Error removing target file: %s"
+msgid "Error getting data from file"
+msgstr "ফাইল থেকে তথ্য প্রাপ্ত করতে ত্রুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "আইকন নির্দেশক '%s' ত্রুটিপূর্ণ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+#| msgid "Error seeking in stream on drive %s"
+msgid "Error seeking in stream on camera %s"
+msgstr "ক্যামেরা %s-র মধ্যে স্ট্রিম seek করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "এটি একটি ডিরেক্টরি নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+#| msgid "File doesn't exist"
+msgid "Failed to get folder list"
+msgstr "ফোল্ডার তালিকা প্রাপ্ত করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+#| msgid "Target file exists"
+msgid "Failed to get file list"
+msgstr "ফাইলের তালিকা প্রাপ্ত করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+#| msgid "Error creating socket: %s"
+msgid "Error creating directory"
+msgstr "ডিরেক্টরি নির্মাণ করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+#| msgid "Target file already exists"
+msgid "Name already exists"
+msgstr "উল্লিখিত নাম বর্তমানে উপস্থিত"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+#| msgid "filename too long"
+msgid "New name too long"
+msgstr "নতুন নাম অত্যাধিক লম্বা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+#| msgid "Error sending fd: %s"
+msgid "Error renaming dir"
+msgstr "ডিরেক্টরির নাম পরিবর্তন করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+#| msgid "Error moving file: %s"
+msgid "Error renaming file"
+msgstr "ফাইলের নাম পরিবর্তন করতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+#| msgid "Directory not empty"
+msgid "Directory '%s' is not empty"
+msgstr "ডিরেক্টরি '%s' ফাঁকা নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+#| msgid "Error deleting file: %s"
+msgid "Error deleting directory"
+msgstr "ডিরেক্টরি মুছে ফেলতে সমস্যা"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+#| msgid "Error deleting file: %s"
+msgid "Error deleting file"
+msgstr "ফাইল মুছে ফেলতে ত্রুটি"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+#| msgid "Can't open directory"
+msgid "Can't write to directory"
+msgstr "ডিরেক্টরির মধ্যে লেখা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "সংযোজন করার উদ্দেশ্যে নতুন ফাইল বরাদ্দ করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "সংযোজন করার উদ্দেশ্যে চিহ্নিত ফাইল পড়তে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "সংযোজন করার উদ্দেশ্যে চিহ্নিত ফাইলের তথ্য প্রাপ্ত করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+#| msgid "Error deleting file: %s"
+msgid "Error writing file"
+msgstr "ফাইলে লিখতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+#| msgid "Not a directory"
+msgid "Not supported (not same directory)"
+msgstr "সমর্থিত নয় (এক ডিরেক্টরি নয়)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "সমর্থিত নয় (src ও dst উভয় ডিরেক্টরি)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "সমর্থিত নয় (src একটি ডিরেক্টরি, dst একটি উপস্থিত ফাইল)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "সমর্থিত নয় (src একটি ফাইল, dst একটি ডিরেক্টরি)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP Client ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (এনকোডিং সঠিক নয়)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ডিরেক্টরি সংক্রান্ত সুচনাপ্রদান ব্যবস্থা বর্তমানে সমর্থিত নয়"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows Network"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Network Location Monitor"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s, %s-র উপর"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB সমর্থন উপলব্ধ নয়। অনুগ্রহ করে আপনার সফ্টওয়্যার বিক্রেতার সাথে যোগাযোগ করুন"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "ডিভাইসের সাথে সংযোগ বিচ্ছিন্ন হয়েছে"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "ডিভাইস দ্বারা প্রয়োগকারী সফ্টওয়্যার আপডেট করা আবশ্যক"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh প্রোগ্রাম অপ্রত্যাশিতভাবে বন্ধ হয়ে গেছে"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "হোস্টের নাম অজ্ঞাত"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "হোস্টের সাথে সংযোগের পথ পাওয়া যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "সার্ভার সংযোগ প্রত্যাখ্যান করেছে"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "হোস্ট-কি যাচাই করা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh প্রোগ্রাম তৈরি করা যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh প্রোগ্রাম তৈরি করা যায়নি: %s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr "লগ-ইন করার সময়সীমার মেয়াদ উত্তীর্ণ হয়েছে"
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr "কি-র জন্য পাসফ্রেজ লিখুন"
+
+#: ../daemon/gvfsbackendsftp.c:857
+msgid "Enter password"
+msgstr "পাসওয়ার্ড লিখুন"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "পাসওয়ার্ড পাঠানো সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "তথাপি লগ-ইন করা হবে"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Cancel Login"
+msgstr "লগ-ইন বাতিল করুন"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"দূরবর্তী কম্পিউটার (%s) এর পরিচয় অজানা।\n"
+"কম্পিউটারে প্রথমবার লগ-ইন করলে এটি স্বাভাবিক।\n"
+"\n"
+"%s-টি দূরবর্তী কম্পিউটারের পরিচিতি। আপনি যদি নিশ্চিত হতে চান তাহলে সিস্টেম "
+"অ্যাডমিনিস্ট্রেটারের সাথে যোগাযোগ করুন।"
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "লগ-ইন ডায়লগ বন্ধ করা হয়েছে"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr "হোস্টের পরিচয়পত্র প্রদান করা সম্ভব হয়নি"
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+msgid "Protocol error"
+msgstr "প্রোটোকল সংক্রান্ত ত্রুটি"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+#| msgid "ftp as %s on %s"
+msgid "sftp for %s on %s"
+msgstr "%s-র জন্য %s-এ sftp করুন"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "%s-র উপর sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr "সমর্থিত ssh কম্যান্ড খুঁজে পাওয়া যায়নি"
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "বিফলতা"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "প্রাপ্ত উত্তর সঠিক নয়"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead-র মধ্যে অবৈধ icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "ব্যাক-আপ ফাইল তৈরি করতে ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "অস্থায়ী ফাইল প্রস্তুত করতে অক্ষম"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "একটি ডিরেক্টরির উপর অন্য ডিরেক্টরি সরিয়ে ফেলা যাবে না"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s শেয়ার %s-র উপর স্থাপিত এবং এই শেয়ারটির জন্য পাসওয়ার্ড প্রয়োজন"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "অভ্যন্তরীণ ত্রুটি (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows শেয়ার মাউন্ট করতে অক্ষম"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "seek-র ধরন সমর্থিত নয়"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "ব্যাক-আপ ফাইল প্রস্তুত করা যায়নি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ফাইল মুছে ফেলতে ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ফাইল সরাতে ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "উদ্দিষ্ট ফাইল সরিয়ে ফেলতে ত্রুটি: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "রিকার্সিভ রূপে ডিরেক্টরটি স্থানান্তর করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows Shares Filesystem Service"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+#| msgid "Password required for share %s on %s"
+msgid "Password required for %s"
+msgstr "%s-র জন্য পাসওয়ার্ড প্রয়োজন"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s-এ Windows শেয়ারসমূহ"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "সার্ভার থেকে শেয়ারের তালিকা প্রাপ্ত করতে ব্যর্থ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "এই ফাইলটি মাউন্ট করা সম্ভব নয়"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "এটি স্বাভাবিক ফাইল নয়"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows Network Filesystem Service"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "আবর্জনার ফোল্ডার মুছে ফেলা নাও হতে পারে"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "আবর্জনার বাক্সে উপস্থিত বস্তু পরিবর্তন করা সম্ভব না হতে পারে"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "আবর্জনা"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "চিহ্নিত ব্যাক-এন্ড প্রকার অসমর্থিত"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd প্রদানে ত্রুটি: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "ব্যাক-এন্ড symlink সমর্থন করে না"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "dbus সংবাদ সঠিক নয়"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "পুরানো daemon-কে পরিবর্তন করুন"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "fuse চালু করা হবে না।"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Daemon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS-র প্রধান daemon"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "অধিক তথ্যের জন্য \"%s --help\" ব্যবহার করুন"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "spawn করা চাইল্ড থেকে প্রাপ্ত আর্গুমেন্টগুলি বৈধ নয়"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount করা যায়নি: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "নির্দিষ্ট স্থান মাউন্ট করা হয়নি"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "নির্দিষ্ট স্থানটি সমর্থিত নয়"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "স্থানটি বর্তমানে মাউন্ট করা হয়েছে"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "স্থানটি মাউন্ট করা যাবে না"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ফাঁকা CD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ফাঁকা CD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ফাঁকা CD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ফাঁকা DVD-ROM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ফাঁকা DVD-RAM ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ফাঁকা DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ফাঁকা DVD+R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ফাঁকা DVD+RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ফাঁকা DVD+R DL ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ফাঁকা Blu-Ray ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ফাঁকা Blu-Ray R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ফাঁকা Blu-Ray RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ফাঁকা HD DVD ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ফাঁকা HD DVD-R ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ফাঁকা HD DVD-RW ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ফাঁকা MO ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "ডিস্ক"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ফাঁকা ডিস্ক"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ড্রাইভ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ফ্লপি ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "সফ্টওয়্যার RAID ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "টেপ ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "বৃহৎ মাপে সংরক্ষণের ড্রাইভ"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "মিডিয়াতে একাধিক ভলিউম ব্যস্ত; মিডিয়া বের করা যায়নি"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f মেগাবাইট"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f গিগাবাইট"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "অডিও/তথ্য সংমিশ্রিত ডিস্ক"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s মিডিয়া"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s এনক্রিপ্ট করা তথ্য"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ফাইল খুলতে ত্রুটি: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout এ লিখতে ত্রুটি"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: পাঠ করতে ত্রুটি: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:বন্ধ করতে ত্রুটি: %s\n"
+
+# this looks like an option from the command line, hence not translating
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - concatenate LOCATIONS to standard output."
+
+# this looks like an option from the command line, hence not translating
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+
+# this looks like an option from the command line, hence not translating
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: অবস্থান অনুপস্থিত"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: চিহ্নিত অবস্থান খুলতে ত্রুটি: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: অ্যাপ্লিকেশন আরম্ভ করতে ত্রুটি: %s\n"
+
+# this looks like an option from the command line, hence not translating
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - open FILES with registered application."
+
+# this looks like an option from the command line, hence not translating
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+
diff --git a/trunk/po/ca.po b/trunk/po/ca.po
new file mode 100644
index 00000000..57b1744d
--- /dev/null
+++ b/trunk/po/ca.po
@@ -0,0 +1,1752 @@
+# Catalan translation of gvfs.
+# Copyright (C) 2008, Free Software Foundation Inc.
+# This file is distributed under the same license as the gvfs package.
+# Gil Forcada <gilforcada@guifi.net>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-03 21:31+0100\n"
+"PO-Revision-Date: 2009-02-23 20:38+0100\n"
+"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
+"Language-Team: Catalan <tradgnome@softcatala.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"L'operació no està implementada. Els fitxers estan en diferents punts de "
+"muntatge"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "«get_info» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "«query_info» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "No s'ha pogut obtenir el descriptor de fitxer del flux"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "«open» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "No s'ha obtingut el descriptor de fitxer del flux"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "«call» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "«get_filesystem_info» ha retornat un valor no vàlid"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "No s'ha pogut trobar el punt de muntatge de tancament"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "El nom de fitxer %s no és vàlid"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "«query_filesystem_info» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "«monitor_file» ha retornat un valor no vàlid"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "S'ha cancel·lat l'operació"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Error en el protocol del flux: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Final del flux"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "No està implementada la cerca en el flux"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+"S'ha produït un error en obtenir la informació del punt de muntatge: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "S'ha produït un error en connectar-se al dimoni: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "«open_icon_for_read» ha retornat un valor no vàlid"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "S'ha produït un error en crear el sòcol: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "S'ha produït un error en connectar-se al sòcol: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "El format d'informació del fitxer no és vàlid"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "El contingut de la llista d'informació dels atributs no és vàlid"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "S'ha produït un error en inicialitzar l'Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "S'ha produït un error en crear el resoledor Avahi: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "S'ha produït un error en resoldre el servei «%s» «%s» en el domini «%s»"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"S'ha produït un error en resoldre el servei «%s» «%s» en el domini «%s». Manca "
+"algun registre TXT. Claus necessàries: «%s»"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "S'ha excedit el temps en resoldre el servei «%s» «%s» en el domini «%s»"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "encoded_triple «%s» del dns-sd mal formada"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "No es pot gestionar la versió %d de la codificació del GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Dades d'entrada mal formades per al GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "S'ha produït un error en connectar-se al D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Sistema de fitxers %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Error: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Ús: %s --spawner identificador_dbus camí_a_l'objecte"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Ús: %s clau=valor clau=valor ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "No s'ha especificat el tipus de muntatge"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "ja s'està fent servir el punt de muntatge %s"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "s'ha produït un error en iniciar el dimoni de muntatge"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1912
+#, c-format
+msgid "/ on %s"
+msgstr "/ a %s"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "No hostname specified"
+msgstr "No s'ha especificat el nom de la màquina"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Especificació de muntatge no vàlida"
+
+#: ../daemon/gvfsbackendarchive.c:639 ../daemon/gvfsbackendarchive.c:689
+#: ../daemon/gvfsbackendarchive.c:718 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "No existeix el fitxer"
+
+#: ../daemon/gvfsbackendarchive.c:727 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "El fitxer no és un directori"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Grava"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "No s'ha pogut crear un directori temporal"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendburn.c:975
+#: ../daemon/gvfsbackendburn.c:1011 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "No existeix el fitxer o directori"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "El directori no és buit"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:907
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "No es pot copiar el fitxer al directori"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Creador de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:927 ../daemon/gvfsbackendburn.c:989
+#: ../daemon/gvfsbackendburn.c:993 ../daemon/gvfsbackendburn.c:1003
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Existeix el fitxer"
+
+#: ../daemon/gvfsbackendburn.c:830 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "El rerefons no ha implementat l'operació"
+
+#: ../daemon/gvfsbackendburn.c:855
+msgid "No such file or directory in target path"
+msgstr "No existeix el fitxer o directori en el camí objectiu"
+
+#: ../daemon/gvfsbackendburn.c:878 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "No es pot copiar el directori al directori"
+
+#: ../daemon/gvfsbackendburn.c:887 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Ja existeix el fitxer de destinació"
+
+#: ../daemon/gvfsbackendburn.c:894 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "No es pot copiar el directori de forma recursiva"
+
+#: ../daemon/gvfsbackendburn.c:953 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "No és implementat"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "No s'ha pogut connectar al bus del sistema"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "No s'ha pogut crear el context libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "No s'ha pogut inicialitzar la libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "No s'ha especificat la unitat"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "No s'ha pogut trobar la unitat %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "La unitat %s no conté fitxers d'àudio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "CDDA muntat a %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:333 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disc d'àudio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "El sistema de fitxers està ocupat: %d fitxer obert"
+msgstr[1] "El sistema de fitxers està ocupat: %d fitxers oberts"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "No hi ha el fitxer %s en la unitat %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "S'ha produït un error del «paranoia» en la unitat %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "S'ha produït un error en cercar en el flux de la unitat %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "No hi ha cap fitxer"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "No existeix el fitxer, o bé, no és una pista d'àudio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Servei de sistema de fitxers de CD d'àudio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Ordinador"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistema de fitxers"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:691
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "No es pot obrir el directori"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "No es pot obrir el fitxer muntable"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1055
+#, c-format
+msgid "Internal error: %s"
+msgstr "Error intern: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "No es pot muntar el fitxer"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "No hi ha cap suport en la unitat"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "No és un fitxer muntable"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "No es pot desmuntar el fitxer"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "No es pot expulsar el fitxer"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Error HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "No s'ha pogut analitzar la resposta"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Resposta buida"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Resposta inesperada del servidor"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Resposta no vàlida"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Recurs compartit de WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Introduïu la contrasenya per a %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Introduïu la contrasenya del servidor intermediari"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "No és un recurs compartit habilitat per a WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV a %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "No s'ha pogut crear la sol·licitud"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3783
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Ja existeix el fitxer de destinació"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2950
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "S'ha modificat el fitxer des d'un altre programa"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "No s'ha pogut crear el fitxer de còpia de seguretat"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Xarxa local"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "No es pot fer un seguiment del fitxer o directori."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Xarxa"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "No es poden utilitzar comptes"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "L'ordinador remot ha tancat la connexió"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"No s'ha pogut obrir una connexió de dades. Potser el tallafocs no ho permet?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "S'ha tancat la connexió de dades"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Ha fallat l'operació"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "No hi ha espai lliure en el servidor"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4094
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Operació no implementada"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Permís denegat"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Tipus de pàgina desconeguda"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nom de fitxer no vàlid"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "S'ha rebut una resposta no vàlida"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "transmissió trencada"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "No s'ha pogut connectar amb l'ordinador"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Introduïu la contrasenya per a l'FTP com a %s a %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Introduïu la contrasenya per a l'FTP a %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:877
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "S'ha cancel·lat el diàleg de contrasenya"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "FTP a %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "FTP com a %s a %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1976
+#: ../daemon/gvfsbackendsftp.c:3774
+msgid "File is directory"
+msgstr "El fitxer és un directori"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2811
+msgid "backups not supported yet"
+msgstr "encara no es poden utilitzar còpies de seguretat"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "el nom de fitxer és massa llarg"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nom de fitxer de destinació no vàlid"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ja existeix el directori o el fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: no existeix el fitxer o directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: nom de fitxer no vàlid"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: no és implementat"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Càmera digital (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Càmera %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Reproductor de música de %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Càmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Reproductor de música"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "No s'ha especificat el dispositiu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "No s'ha pogut crear el context gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "S'ha produït un error en crear la càmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "S'ha produït un error en carregar la informació del dispositiu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "S'ha produït un error en consultar la informació del dispositiu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "S'ha produït un error en obtenir la informació del dispositiu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr ""
+"S'ha produït un error en configurar el port de comunicacions de la càmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "S'ha produït un error en inicialitzar la càmera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gPhoto2 muntat a %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "No s'ha especificat cap càmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "S'ha produït un error en crear l'objecte de fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "S'ha produït un error en obtenir el fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "S'ha produït un error obtenir dades del fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificador d'icona mal formada «%s»"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "S'ha produït un error en cercar en el flux de la càmera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "No és un directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "No s'ha pogut obtenir el llistat del directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "No s'ha pogut obtenir el llistat de fitxers"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "S'ha produït un error en crear el directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Ja existeix el nom"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "El nom nou és massa llarg"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "S'ha produït un error en canviar el nom del directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "S'ha produït un error en canviar el nom del fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "El directori «%s» no és buit"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "S'ha produït un error en suprimir el directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "S'ha produït un error en suprimir el fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "No es pot escriure en el directori"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "No s'ha pogut ubicar el fitxer nou al que afegir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "No s'ha pogut llegir el fitxer al que afegir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "No s'ha pogut obtenir dades del fitxer al que afegir"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "S'ha produït un error en escriure el fitxer"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "No està implementat (no són en el mateix directori)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "No està implementat (l'orgien i la destinació són directoris)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+"No està implementat (l'orgien és un directori i la destinació un fitxer "
+"existent)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+"No està implementat (l'origen és un fitxer i la destinació un directori)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Error en el client HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1900
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codificació incorrecta)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "No està implementada la notificació del directori"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Xarxa de Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Orinadors de la xarxa"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s a %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+"Manca els programes per gestionar USB. Contacteu amb el vostre proveïdor"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "S'ha perdut la connexió amb el dispositiu"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "El dispositiu necessita una actualització de programari"
+
+#: ../daemon/gvfsbackendsftp.c:291
+msgid "ssh program unexpectedly exited"
+msgstr "el programa SSH ha sortit inesperadament"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Es desconeix el nom de l'ordinador"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "No hi ha cap ruta fins a l'ordinador"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "El servidor ha rebutjat la connexió"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Ha fallat la verificació de la clau de l'ordinador"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "No s'ha pogut engendrar el programa SSH"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "No s'ha pogut engendrar el programa SSH: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:783
+msgid "Timed out when logging in"
+msgstr "Ha expirat el temps d'identificació"
+
+#: ../daemon/gvfsbackendsftp.c:861
+msgid "Enter passphrase for key"
+msgstr "Introduïu la contrasenya per a la clau"
+
+#: ../daemon/gvfsbackendsftp.c:863
+msgid "Enter password"
+msgstr "Introduïu la contrasenya"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send password"
+msgstr "No s'ha pogut enviar la contrasenya"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Log In Anyway"
+msgstr "Entra igualment"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Cancel Login"
+msgstr "Cancel·la l'entrada"
+
+#: ../daemon/gvfsbackendsftp.c:957
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Es desconeix la identitat de l'ordinador remot (%s).\n"
+"Això passa quan entreu a un ordinador per primera vegada.\n"
+"\n"
+"La identitat que ha enviat l'ordinador remot és %s. Si voleu estar "
+"completament segur, contacteu amb l'administrador del sistema."
+
+#: ../daemon/gvfsbackendsftp.c:977
+msgid "Login dialog cancelled"
+msgstr "S'ha cancel·lat el diàleg d'entrada"
+
+#: ../daemon/gvfsbackendsftp.c:997
+msgid "Can't send host identity confirmation"
+msgstr "No s'ha pogut enviar la confirmació de la identitat de l'ordinador"
+
+#: ../daemon/gvfsbackendsftp.c:1490 ../daemon/gvfsbackendsftp.c:1513
+msgid "Protocol error"
+msgstr "Error en el protocol"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1538
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "SFTP com a %s a %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1541
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp a %s"
+
+#: ../daemon/gvfsbackendsftp.c:1567
+msgid "Unable to find supported ssh command"
+msgstr "No s'ha pogut trobar l'ordre de SSH implementada"
+
+#: ../daemon/gvfsbackendsftp.c:1985
+msgid "Failure"
+msgstr "Fallada"
+
+#: ../daemon/gvfsbackendsftp.c:2041 ../daemon/gvfsbackendsftp.c:2120
+#: ../daemon/gvfsbackendsftp.c:2131 ../daemon/gvfsbackendsftp.c:2187
+#: ../daemon/gvfsbackendsftp.c:2273 ../daemon/gvfsbackendsftp.c:2323
+#: ../daemon/gvfsbackendsftp.c:2369 ../daemon/gvfsbackendsftp.c:2444
+#: ../daemon/gvfsbackendsftp.c:2551 ../daemon/gvfsbackendsftp.c:2591
+#: ../daemon/gvfsbackendsftp.c:2641 ../daemon/gvfsbackendsftp.c:2713
+#: ../daemon/gvfsbackendsftp.c:2725 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2825 ../daemon/gvfsbackendsftp.c:3002
+#: ../daemon/gvfsbackendsftp.c:3027 ../daemon/gvfsbackendsftp.c:3082
+#: ../daemon/gvfsbackendsftp.c:3139 ../daemon/gvfsbackendsftp.c:3410
+#: ../daemon/gvfsbackendsftp.c:3477 ../daemon/gvfsbackendsftp.c:3612
+#: ../daemon/gvfsbackendsftp.c:3672 ../daemon/gvfsbackendsftp.c:3707
+#: ../daemon/gvfsbackendsftp.c:3735 ../daemon/gvfsbackendsftp.c:3843
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3933
+#: ../daemon/gvfsbackendsftp.c:3967 ../daemon/gvfsbackendsftp.c:3982
+#: ../daemon/gvfsbackendsftp.c:3997 ../daemon/gvfsbackendsftp.c:4075
+msgid "Invalid reply received"
+msgstr "S'ha rebut una resposta no vàlida"
+
+#: ../daemon/gvfsbackendsftp.c:2093
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "«icon_id» «%s» no vàlid a OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2389
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "S'ha produït un error en crear el fitxer de còpia de seguretat: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2887
+msgid "Unable to create temporary file"
+msgstr "No s'ha pogut crear un fitxer temporal"
+
+#: ../daemon/gvfsbackendsftp.c:3769 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "No es pot moure el directori al directori"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Es requereix contrasenya per al recurs compartit %s a %s"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Error intern (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "No s'ha pogut muntar el recurs compartit de Windows"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Tipus de cerca no implementada"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "No s'ha pogut crear el fitxer de còpia de seguretat: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "S'ha produït un error en suprimir el fitxer: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "S'ha produït un error en moure el fitxer: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "S'ha produït un error en suprimir el fitxer objectiu: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "No es pot moure el directori de forma recursiva"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Servei de sistema de fitxers compartits de Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Es requereix contrasenya per a %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Recursos compartits de Windows a %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "No s'ha pogut recuperar la llista de compartits del servidor"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "El fitxer no es pot muntar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "No és un fitxer normal"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Servei de sistema de fitxers en xarxa de Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "No s'hauria de suprimir el directori de la paperera"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "No s'haurien de modificar els elements de la paperera"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Paperera"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipus de rerefons no vàlid"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "S'ha produït un error en enviar el descriptor de fitxer: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "El rerefons no ha implementat els enllaços simbòlics"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "El missatge del D-Bus no és vàlid"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Substitueix el dimoni anterior."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "No iniciïs el FUSE."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Dimoni del GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Dimoni principal del GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Per a més informació proveu «%s --help»."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Arguments no vàlids del fill engendrat"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Ha fallat el muntatge automàtic: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "No està muntada la ubicació especificada"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "No se sap gestionar la ubicació especificada"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Ja està muntada la ubicació"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "La ubicació no és pot muntar"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disc CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disc CD-ROM en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disc CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disc CD-R en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disc CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disc CD-RW en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disc DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disc DVD-ROM en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disc DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disc DVD-RAM en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disc DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disc DVD-RW en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disc DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disc DVD+R en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disc DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disc DVD+RW en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disc DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disc DVD+R DL en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disc Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disc Blu-Ray en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disc Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disc Blu-Ray R en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disc Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disc Blu-Ray RW en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disc HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disc HD DVD en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disc HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disc HD DVD-R en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disc HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disc HD DVD-RW en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disc MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disc MO en blanc"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disc en blanc"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unitat %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unitat %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Unitat de disquet"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unitat de RAID per programari"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unitat USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Unitat ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Unitat SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unitat FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unitat de cinta"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unitat CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unitat MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unitat SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unitat SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unitat Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unitat Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Unitat Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unitat de memòria de massa"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"No s'ha pogut expulsar el suport. Alguns dels volums del suport estan "
+"ocupats."
+
+#: ../monitor/hal/ghalmount.c:167 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:172 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:177 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:331 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disc mesclat d'àudio i dades"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:344 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Suport %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s dades xifrades"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: s'ha produït un error en obrir el fitxer: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, s'ha produït un error en escriure a la sortida estàndard"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: s'ha produït un error en llegir: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:error en tancar: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "UBICACIÓ... - concatena UBICACIONS a la sortida estàndard."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatena fitxers a les ubicacions i imprimeix a la sortida estàndard. "
+"Funciona de la mateixa manera que l'eina «cat» de sempre, però utilitza "
+"l'ubicació del gvfs enlloc de fitxers locals: per exemple, podeu fer servir "
+"com a ubicació per a concatenar coses com smb://servidor/recurs/fitxer.txt."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: utilitzeu un conducte a través del «cat» si necessiteu les seves "
+"opcions de formatació com -n, -T o d'altres."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: manquen les ubicacions"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: s'ha produït un error en obrir la ubicació: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: s'ha produït un error en executar l'aplicació: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "FITXERS... - obre els FITXERS amb l'aplicació registrada."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Obre els fitxers amb l'aplicació registrada predeterminada per a gestionar "
+"aquest tipus de fitxer."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "No està implementada l'operació de consulta d'informació"
+
+#~ msgid "Query info not supported on stream"
+#~ msgstr "No està implementada la consulta d'informació en el flux"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "No es pot suprimir la paperera"
+
+#, fuzzy
+#~ msgid "Can't pull trash"
+#~ msgstr "No es pot suprimir la paperera"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (a la paperera)"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "No està implementada la notificació del directori de la paperera"
+
+#, fuzzy
+#~ msgid "Error creating port info list"
+#~ msgstr "S'ha produït un error en crear el sòcol: %s"
+
+#, fuzzy
+#~ msgid "Error getting port info from port info list"
+#~ msgstr ""
+#~ "S'ha produït un error en obtenir la informació del punt de muntatge: %s"
+
+#, fuzzy
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "El sistema de fitxers està ocupat: %d fitxer obert"
+
+#, fuzzy
+#~ msgid "Error listing folders"
+#~ msgstr "S'ha produït un error en suprimir el fitxer: %s"
+
+#, fuzzy
+#~ msgid "Error listing files in folder"
+#~ msgstr "S'ha produït un error en suprimir el fitxer: %s"
+
+#~ msgid "File unavailable"
+#~ msgstr "El fitxer no està disponible"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Suport de %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Suport de %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Suport de %.1f GB"
+
+#~ msgid "Invalid reply from server."
+#~ msgstr "El servidor ha enviat una resposta no vàlida."
+
+#~ msgid "Operation cancelled"
+#~ msgstr "S'ha cancel·lat l'operació"
+
+#~ msgid "Invalid username"
+#~ msgstr "Nom d'usuari no vàlid"
+
+#~ msgid "Invalid password"
+#~ msgstr "Contrasenya no vàlida"
+
+#~ msgid "FTP on %s"
+#~ msgstr "FTP a %s"
+
+#~ msgid "FTP on %s:%u"
+#~ msgstr "FTP a %s:%u"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Disc d'àudio a %s"
+
+#~ msgid "The file does not exist"
+#~ msgstr "No existeix el fitxer"
+
+#~ msgid "CD Burner"
+#~ msgstr "Gravadora de CD"
+
+#~ msgid "No fd passing socket available"
+#~ msgstr "No hi ha cap sòcol de passada de descriptor de fitxer disponible"
+
+#~ msgid "Containing mount does not exist"
+#~ msgstr "No existeix el punt de muntatge contenidor"
+
+#~ msgid "Failed to allocate smb context"
+#~ msgstr "No s'ha pogut ubicar el context de SMB"
+
+#~ msgid "Failed to initialize smb context"
+#~ msgstr "No s'ha pogut inicialitzar el context de SMB"
+
+#~ msgid "accept of extra fd failed"
+#~ msgstr "ha fallat l'acceptació d'un descriptor de fitxer extra"
+
+#~ msgid "object registration failed"
+#~ msgstr "ha fallat el registre de l'objecte"
diff --git a/trunk/po/cs.po b/trunk/po/cs.po
new file mode 100644
index 00000000..20dccf17
--- /dev/null
+++ b/trunk/po/cs.po
@@ -0,0 +1,1644 @@
+# Czech translation of gvfs.
+# Copyright (C) 2008, 2009 the author(s) of gvfs.
+# This file is distributed under the same license as the gvfs package.
+# Petr Kovar <pknbe@volny.cz>, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-08 19:24+0100\n"
+"PO-Revision-Date: 2009-03-08 19:21+0100\n"
+"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
+"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operace není podporována, soubory na rozdílných připojeních"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Neplatná návratová hodnota od get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Neplatná návratová hodnota od query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Nelze získat deskriptor proudového souboru"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Neplatná návratová hodnota od open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Nezískán deskriptor proudového souboru"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Neplatná návratová hodnota od call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Neplatná návratová hodnota od get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nelze nalézt viditelné připojení"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Neplatný název souboru %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Neplatná návratová hodnota od query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Neplatná návratová hodnota od monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Neplatná návratová hodnota od monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:298
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "Operace byla zrušena"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Chyba v proudovém protokolu: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Konec proudu"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "Hledání v proudu nepodporováno"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Chyba při získávání informace o připojení: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Chyba při spojování s démonem: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Neplatná návratová hodnota od open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Chyba při vytváření socketu: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Chyba při spojování se socketem: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Neplatný formát informace o souboru"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Neplatný obsah seznamu informací o atributech"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Chyba při spouštění Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Chyba při vytváření překladače Avahi: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Chyba při řešení služby \"%s\" \"%s\" v doméně \"%s\""
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Chyba při řešení služby \"%s\" \"%s\" v doméně \"%s\". Schází jeden nebo "
+"více záznamů TXT. Požadované klíče: \"%s\"."
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Při řešení služby \"%s\" \"%s\" v doméně \"%s\" vypršel čas"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Chybné dns-sd encoded_triple \"%s\""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Nelze zpracovat verzi %d kódování GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Chybná vstupní data u GVfsIcon"
+
+#: ../daemon/daemon-main.c:76 ../daemon/daemon-main.c:226
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Chyba při spojování s D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:91
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Služba systému souborů %s"
+
+#: ../daemon/daemon-main.c:110
+#, c-format
+msgid "Error: %s"
+msgstr "Chyba: %s"
+
+#: ../daemon/daemon-main.c:151
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Použití: %s --spawner dbus-id cesta_objektu"
+
+#: ../daemon/daemon-main.c:175 ../daemon/daemon-main.c:193
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Použití: %s klíč=hodnota klíč=hodnota ..."
+
+#: ../daemon/daemon-main.c:191
+#, c-format
+msgid "No mount type specified"
+msgstr "Nezadán žádný typ připojení"
+
+#: ../daemon/daemon-main.c:261
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "bod připojení %s již běží"
+
+#: ../daemon/daemon-main.c:272
+msgid "error starting mount daemon"
+msgstr "chyba při spouštění démona mount"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1912
+#, c-format
+msgid "/ on %s"
+msgstr "/ na %s"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "No hostname specified"
+msgstr "Nebyl zadán název hostitele"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Neplatné určení připojení"
+
+#: ../daemon/gvfsbackendarchive.c:639 ../daemon/gvfsbackendarchive.c:689
+#: ../daemon/gvfsbackendarchive.c:718 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2264 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Soubor neexistuje"
+
+#: ../daemon/gvfsbackendarchive.c:727 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Soubor není adresářem"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Zápis"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nezdařilo se vytvoření dočasného adresáře"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:717 ../daemon/gvfsbackendburn.c:743
+#: ../daemon/gvfsbackendburn.c:781 ../daemon/gvfsbackendburn.c:972
+#: ../daemon/gvfsbackendburn.c:1008 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Neexistuje žádný takový soubor nebo adresář"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Adresář není prázdný"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:904
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Nelze kopírovat nad adresář"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Tvůrce CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:753 ../daemon/gvfsbackendburn.c:789
+#: ../daemon/gvfsbackendburn.c:924 ../daemon/gvfsbackendburn.c:986
+#: ../daemon/gvfsbackendburn.c:990 ../daemon/gvfsbackendburn.c:1000
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Soubor existuje"
+
+#: ../daemon/gvfsbackendburn.c:828 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operace není podpůrnou vrstvou podporována"
+
+#: ../daemon/gvfsbackendburn.c:853
+msgid "No such file or directory in target path"
+msgstr "V cílové cestě neexistuje žádný takový soubor nebo adresář"
+
+#: ../daemon/gvfsbackendburn.c:876 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Nelze kopírovat adresář nad adresář"
+
+#: ../daemon/gvfsbackendburn.c:885 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Cílový soubor existuje"
+
+#: ../daemon/gvfsbackendburn.c:892 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Nelze rekurzivně kopírovat adresář"
+
+#: ../daemon/gvfsbackendburn.c:950 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Nepodporováno"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Nezdařilo se připojit k systémové sběrnici"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Nelze vytvořit kontext libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Nelze spustit libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nezadána žádná mechanika"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Nelze najít mechaniku %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Mechanika %s neobsahuje zvukové soubory"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "připojení cdda na %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325 ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "Zvukový disk"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Systém souborů je zaneprázdněn: %d otevřený soubor"
+msgstr[1] "Systém souborů je zaneprázdněn: %d otevřené soubory"
+msgstr[2] "Systém souborů je zaneprázdněn: %d otevřených souborů"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Žádný takový soubor %s na mechanice %s neexistuje"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Chyba knihovny paranoia na mechanice %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Chyba při hledání v proudu na mechanice %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Žádný takový soubor neexistuje"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Soubor neexistuje nebo není zvukovou stopou"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Služba systému souborů zvukového CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Počítač"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Systém souborů"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:691
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Nelze otevřít adresář"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Nelze otevřít připojitelný soubor"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1055
+#, c-format
+msgid "Internal error: %s"
+msgstr "Vnitřní chyba: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Nelze připojit soubor"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "V mechanice není médium"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Není připojitelným souborem"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Nelze odpojit soubor"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Nelze vysunout soubor"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Chyba HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Nelze analyzovat odpověď"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Prázdná odpověď"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Neočekávaná odpověď od serveru"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Neplatná odpověď"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Sdílení WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Zadejte heslo k %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Zadejte prosím heslo proxy"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Není sdílením s povoleným WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV na %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Nelze vytvořit požadavek"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528 ../daemon/gvfsbackendsftp.c:3783
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Cílový soubor už existuje"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2950
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "Soubor byl upraven externě"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "Selhala tvorba záložního souboru"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Místní síť"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Nelze sledovat soubor nebo adresář."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Síť"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Účty nejsou podporovány"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Hostitel ukončil spojení"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Nelze otevřít datové spojení. Možná to znemožňuje firewall?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Datové spojení ukončeno"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Operace selhala"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Na serveru není volné místo"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4094
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Operace nepodporována"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Přístup odepřen"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Neznámý typ strany"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "Neplatný název souboru"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "Neplatná odpověď"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "chybný přenos"
+
+#: ../daemon/gvfsbackendftp.c:713 ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "Nezdařilo se připojit k hostiteli"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Zadejte heslo k ftp jako %s na %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Zadejte heslo k ftp na %s"
+
+#: ../daemon/gvfsbackendftp.c:1525 ../daemon/gvfsbackendsftp.c:877
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Dialog zadání hesla zrušen"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp na %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp jako %s na %s"
+
+#: ../daemon/gvfsbackendftp.c:1692 ../daemon/gvfsbackendsftp.c:1976
+#: ../daemon/gvfsbackendsftp.c:3774
+msgid "File is directory"
+msgstr "Soubor je adresářem"
+
+#: ../daemon/gvfsbackendftp.c:1914 ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2811
+msgid "backups not supported yet"
+msgstr "zálohy zatím nejsou podporovány"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "název souboru je příliš dlouhý"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "Neplatný název cílového souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Adresář nebo soubor existuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Neexistuje žádný takový soubor nebo adresář"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Neplatný název souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nepodporováno"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitální fotoaparát (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Fotoaparát %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Zvukový přehrávač %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Fotoaparát"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Zvukový přehrávač"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Nezadáno žádné zařízení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Nelze vytvořit kontext gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Chyba při vytváření prvku fotoaparátu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Chyba při nahrávání informací o zařízení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Chyba při vyhledávání informací o zařízení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Chyba při získávání informací o zařízení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Chyba při nastavování komunikačního portu fotoaparátu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Chyba při spouštění fotoaparátu"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "připojení gphoto2 na %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Nebyl zadán žádný fotoaparát"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Chyba při vytváření objektu souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Chyba při získávání souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Chyba při získávání dat ze souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Chybný identifikátor ikony \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Chyba při hledání v proudu ve fotoaparátu %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Není adresářem"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Nezdařilo se získání seznamu složek"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Nezdařilo se získání seznamu souborů"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Chyba při vytváření adresáře"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Název již existuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Nový název je příliš dlouhý"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Chyba při přejmenovávání adresáře"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Chyba při přejmenovávání souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Adresář \"%s\" není prázdný"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Chyba při mazání adresáře"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Chyba při mazání souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Nelze zapisovat do adresáře"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Nelze alokovat nový soubor, ke kterému má proběhnout přidání"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Nelze přečíst soubor, ke kterému má proběhnout přidání"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Nelze získat data souboru, ke kterému má proběhnout přidání"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Chyba při zápisu souboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Nepodporováno (nejedná se o stejný adresář)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nepodporováno (zdroj je adresář, cíl je adresář)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nepodporováno (zdroj je adresář, cíl je existující soubor)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nepodporováno (zdroj je soubor, cíl je adresář)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Klientská chyba HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1900
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (neplatné kódování)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Adresářové upozornění nepodporováno"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Síť Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Sledování síťových umístění"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s na %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Schází podpora USB: Kontaktujte prosím dodavatele softwaru."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Ztraceno spojení se zařízením"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Zařízení vyžaduje softwarovou aktualizaci"
+
+#: ../daemon/gvfsbackendsftp.c:291
+msgid "ssh program unexpectedly exited"
+msgstr "program ssh neočekávaně skončil"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Název hostitele není znám"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "K hostiteli neexistuje cesta"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "Spojení odmítnuto serverem"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Ověření klíče hostitele selhalo"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "Nelze spustit program ssh"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Nelze spustit program ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:783
+msgid "Timed out when logging in"
+msgstr "Při přihlašování vypršel časový limit"
+
+#: ../daemon/gvfsbackendsftp.c:861
+msgid "Enter passphrase for key"
+msgstr "Zadejte heslo ke klíči"
+
+#: ../daemon/gvfsbackendsftp.c:863
+msgid "Enter password"
+msgstr "Zadejte heslo"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send password"
+msgstr "Nelze odeslat heslo"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Log In Anyway"
+msgstr "Přesto se přihlásit"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Cancel Login"
+msgstr "Zrušit přihlášení"
+
+#: ../daemon/gvfsbackendsftp.c:957
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identita vzdáleného počítače (%s) je neznámá.\n"
+"K tomuto dochází v případě prvního přihlášení k počítači.\n"
+"\n"
+"Identita zaslaná vzdáleným počítačem má podobu %s. Chcete-li mít jistotu, že "
+"je bezpečné pokračovat, kontaktujte prosím správce systému."
+
+#: ../daemon/gvfsbackendsftp.c:977
+msgid "Login dialog cancelled"
+msgstr "Přihlašovací dialog zrušen"
+
+#: ../daemon/gvfsbackendsftp.c:997
+msgid "Can't send host identity confirmation"
+msgstr "Nelze odeslat potvrzení identity hostitele"
+
+#: ../daemon/gvfsbackendsftp.c:1490 ../daemon/gvfsbackendsftp.c:1513
+msgid "Protocol error"
+msgstr "Chyba protokolu"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1538
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp jako %s na %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1541
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp na %s"
+
+#: ../daemon/gvfsbackendsftp.c:1567
+msgid "Unable to find supported ssh command"
+msgstr "Nezdařilo se nalézt podporovaný příkaz ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1985
+msgid "Failure"
+msgstr "Selhání"
+
+#: ../daemon/gvfsbackendsftp.c:2041 ../daemon/gvfsbackendsftp.c:2120
+#: ../daemon/gvfsbackendsftp.c:2131 ../daemon/gvfsbackendsftp.c:2187
+#: ../daemon/gvfsbackendsftp.c:2273 ../daemon/gvfsbackendsftp.c:2323
+#: ../daemon/gvfsbackendsftp.c:2369 ../daemon/gvfsbackendsftp.c:2444
+#: ../daemon/gvfsbackendsftp.c:2551 ../daemon/gvfsbackendsftp.c:2591
+#: ../daemon/gvfsbackendsftp.c:2641 ../daemon/gvfsbackendsftp.c:2713
+#: ../daemon/gvfsbackendsftp.c:2725 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2825 ../daemon/gvfsbackendsftp.c:3002
+#: ../daemon/gvfsbackendsftp.c:3027 ../daemon/gvfsbackendsftp.c:3082
+#: ../daemon/gvfsbackendsftp.c:3139 ../daemon/gvfsbackendsftp.c:3410
+#: ../daemon/gvfsbackendsftp.c:3477 ../daemon/gvfsbackendsftp.c:3612
+#: ../daemon/gvfsbackendsftp.c:3672 ../daemon/gvfsbackendsftp.c:3707
+#: ../daemon/gvfsbackendsftp.c:3735 ../daemon/gvfsbackendsftp.c:3843
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3933
+#: ../daemon/gvfsbackendsftp.c:3967 ../daemon/gvfsbackendsftp.c:3982
+#: ../daemon/gvfsbackendsftp.c:3997 ../daemon/gvfsbackendsftp.c:4075
+msgid "Invalid reply received"
+msgstr "Přijata neplatná odpověď"
+
+#: ../daemon/gvfsbackendsftp.c:2093
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Neplatné icon_id \"%s\" v OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2389
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Chyba při vytváření záložního souboru: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2887
+msgid "Unable to create temporary file"
+msgstr "Nelze vytvořit dočasný soubor"
+
+#: ../daemon/gvfsbackendsftp.c:3769 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "Nelze přesunout adresář nad adresář"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Ke sdílení %s na %s je vyžadováno heslo"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Vnitřní chyba (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Selhalo připojení sdílení Windows"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Nepodporovaný typ hledání"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Tvorba záložního souboru selhala: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Chyba při mazání souboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Chyba při přesouvání souboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Chyba při odstraňování cílového souboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "Nelze rekurzivně přesunout adresář"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Služba systému souborů sdílení prostředků Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s vyžaduje heslo"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Sdílení Windows na %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Ze serveru se nezdařilo získat seznam sdílení"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Soubor není připojitelný"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Není obyčejným souborem"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Služba systému souborů sítě Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Složka koše nemůže být smazána"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Položky v koši nemohou být měněny"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Koš"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Neplatný typ podpůrné vrstvy"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Chyba při odesílání fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symbolické odkazy nejsou podpůrnou vrstvou podporovány"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Neplatná zpráva dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Nahradit starého démona."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Nespouštět fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Démon GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hlavní démon GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Více informací viz \"%s --help\"."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Neplatné argumenty od spouštěného potomka"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatické připojení selhalo: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Zadané umístění není připojeno"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Zadané umístění není podporováno"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Umístění je již připojeno"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Umístění není připojitelné"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disk CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Prázdný disk CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disk CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Prázdný disk CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disk CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Prázdný disk CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disk DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Prázdný disk DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disk DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Prázdný disk DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disk DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Prázdný disk DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disk DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Prázdný disk DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disk DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Prázdný disk DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disk DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Prázdný disk DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disk Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Prázdný disk Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disk Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Prázdný disk Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disk Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Prázdný disk Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disk HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Prázdný disk HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disk HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Prázdný disk HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disk HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Prázdný disk HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Prázdný disk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Prázdný disk"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Mechanika %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "Mechanika %s"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "Disketová mechanika"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "Softwarové zařízení RAID"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "Mechanika USB"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "Mechanika ATA"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "Mechanika SCSI"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "Mechanika FireWire"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "Pásková mechanika"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "Mechanika CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "Mechanika MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "Mechanika SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "Mechanika SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Mechanika Zip"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Mechanika Jaz"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "Přenosná mechanika"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "Velkokapacitní mechanika"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Nezdařilo se vysunutí média, jeden nebo více svazků na médiu je zaneprázdněn."
+
+#: ../monitor/hal/ghalmount.c:159 ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:164 ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:169 ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:323 ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "Smíšené zvukové a datové CD"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336 ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "Médium %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s - šifrovaná data"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: chyba při otevírání souboru: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, chyba při zápisu do stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: chyba při čtení: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: chyba při zavírání: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "UMÍSTĚNÍ... - spojit UMÍSTĚNÍ do standardního výstupu."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Spojit soubory v umístěních a vypsat na standardní výstup. Pracuje přesně "
+"jako obvyklý nástroj cat, ale namísto místních souborů používá umístění "
+"gvfs: například je ke spojení možné jako umístění použít smb://server/"
+"prostredek/soubor.txt."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Poznámka: je-li třeba formátovací volby typu -n, -T apod., stačí použít "
+"rouru pomocí cat."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: scházejí umístění"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: chyba při otevírání umístění: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: chyba při spouštění aplikace: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "SOUBORY... - otevřít SOUBORY s registrovanými aplikacemi."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Otevře soubor(y) s výchozí aplikací registrovanou k obsluze typu daného "
+"souboru."
diff --git a/trunk/po/da.po b/trunk/po/da.po
new file mode 100644
index 00000000..5a79296e
--- /dev/null
+++ b/trunk/po/da.po
@@ -0,0 +1,1658 @@
+# Danish translation of gvfs
+# Copyright (C) 2008-2009 Free Software Foundation
+# This file is distributed under the same license as the gvfs package.
+#
+# Ask Hjorth Larsen <asklarsen@gmail.com>, 2008, 09.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-15 18:21+0100\n"
+"PO-Revision-Date: 2009-02-15 17:04+0100\n"
+"Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operationen er ikke tilladt, filer er på forskellige monteringspunkter"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Ugyldig returværdi fra get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Ugyldig returværdi fra query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Kunne ikke hente fildeskriptor for strømmen"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Ugyldig returværdi fra open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Hentede ikke fildeskriptor for strømmen"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Ugyldig returværdi fra call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ugyldig returværdi fra get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Kunne ikke finde det omsluttende monteringsobjekt"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ugyldigt filnavn %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ugyldig returværdi fra query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Ugyldig returværdi fra monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Ugyldig returværdi fra monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operationen blev annulleret"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Fejl i strømprotokol: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Slutning af strøm"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Søgning understøttes ikke for denne strøm"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Query-info-operationen understøttes ikke"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Forespørgselsinformation understøttes ikke på strømmen"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Fejl under indhentning af monteringsinformation: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Fejl ved forbindelse til dæmon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Ugyldig returværdi fra open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Fejl ved oprettelse af sokkel: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Fejl ved forbindelse til sokkel: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Ugyldig filinformationsformat"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Ugyldigt indhold af attribut-infoliste"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Fejl ved initiering af Avahi: %s"
+
+# resolver?
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Fejl ved oprettelse af Avahi-opløser: %s"
+
+# resolving?
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Fejl ved opløsning af \"%s\"-tjenesten \"%s\" på domænet \"%s\""
+
+# Gad vide hvad en record er. Dette er forhåbentlig dækkende
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Fejl ved opløsning af \"%s\"-tjenesten \"%s\" på domænet \"%s\". En eller "
+"flere TXT-fortegnelser mangler. Påkrævede nøgler: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Tidsudløb ved opløsning af \"%s\"-tjenesten \"%s\" på domænet \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Fejlformet dsn-sd encoded_triple \"%s\""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Kan ikke håndtere version %d af GVfsIcon-kodningen"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Fejlformet inddata for GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Fejl ved forbindelse til D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s-filsystemstjeneste"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Fejl: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Brug: %s --spawner dbus-id objektsti"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Brug: %s nøgle=værdi nøgle=værdi ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ingen monteringstype angivet"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "monteringspunkt for %s kører allerede"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "fejl ved opstart af monteringsdæmon"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ på %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Intet værtsnavn angivet"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Ugyldig monteringsspecifikation"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Filen findes ikke"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Filen er ikke en mappe"
+
+# name of the backend? Så må vi hellere være forsigtige
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Burn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Kan ikke oprette midlertidig mappe"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Filen eller mappen findes ikke"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Mappen er ikke tom"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Kan ikke kopiere fil over mappe"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD Creator"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Filen findes"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operationen understøttes ikke af backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Filen eller mappen findes ikke i destinationsstien"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Kan ikke kopiere mappe over mappen"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Destinationsfilen findes"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Kan ikke kopiere mappen rekursivt"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Ikke understøttet"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Kan ikke forbinde til systembussen"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Kan ikke oprette libhal-kontekst"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Kan ikke initiere libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Intet drev angivet"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Kan ikke finde drevet %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Drevet %s indeholder ikke lydfiler"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda-montering på %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio-disk"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Filsystemet er optaget: %d åben fil"
+msgstr[1] "Filsystemet er optaget: %d åbne filer"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Filen %s findes ikke på drevet %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Fejl fra \"paranoia\" på drevet %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Fejl ved søgning i strøm på drevet %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Filen findes ikke"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Filen findes ikke eller er ikke et lydspor"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Filsystemstjeneste for Audio-CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Filsystem"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Kan ikke åbne mappe"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Kan ikke åbne monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Intern fejl: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Kan ikke montere fil"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Intet medie i drevet"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ikke en monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Kan ikke afmontere fil"
+
+# ??
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Kan ikke skubbe filen ud"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-fejl: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Kunne ikke fortolke svaret"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Tomt svar"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Uventet svar fra server"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Ugyldigt svar"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV-tjeneste"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Indtast kodeord for %s"
+
+# proxy? Nå, vi skriver det bare...
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Indtast venligst et proxy-kodeord"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Ikke en WebDAV-aktiveret deling"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV på %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Kunne ikke oprette forespørgsel"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Destinationsfilen findes allerede"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Filen blev modificeret udefra"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Oprettelse af sikkerhedskopi af filen slog fejl"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lokalt netværk"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Kan ikke overvåge fil eller mappe."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Netværk"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Kontoerne understøttes ikke"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Værten lukkede forbindelsen"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Kan ikke åbne dataforbindelse. Bliver det forhindret af din brandmur?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Dataforbindelse lukket"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Operationen slog fejl"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Ikke mere plads på serveren"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operationen understøttes ikke"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Adgang nægtet"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Ukendt sidetype"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Ugyldigt filnavn"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Ugyldigt svar"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmission afbrudt"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Kunne ikke forbinde til værten"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Indtast kodeord for ftp som %s på %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Indtast kodeord for ftp på %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Kodeordsdialog afbrudt"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp på %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp som %s på %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Filen er en mappe"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "sikkerhedskopier understøttes endnu ikke"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "filnavnet er for langt"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Ugyldigt destinationsfilnavn"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Mappen eller filen findes"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Ingen sådan fil eller mappe findes"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ugyldigt filnavn"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Ikke understøttet"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalkamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s-kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s-lydafspiller"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Lydafspiller"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Ingen enhed angivet"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Kan ikke oprette gphoto2-kontekst"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Fejl ved oprettelse af kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Fejl under indlæsning af enhedsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Fejl under opslag af enhedsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Fejl ved indhentning af enhedsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Fejl under opsætning af kamerakommunikationsport"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Fejl ved initiering af kamera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2-montering på %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Intet kamera angivet"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Fejl ved oprettelse af filobjekt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Fejl ved hentning af fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Fejl ved hentning af data fra fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Fejlformet ikonidentifikator \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Fejl ved søgning i strøm på kameraet %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ikke en mappe"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Kunne ikke hente mappeliste"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Kunne ikke hente filliste"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Fejl ved oprettelse af mappe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Navnet findes allerede"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Det nye navn er for langt"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Fejl ved omdøbning af mappe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Fejl ved omdøbning af fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Mappen \"%s\" er ikke tom"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Fejl ved sletning af mappe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Fejl ved sletning af fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Kan ikke skrive til mappe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Kan ikke allokere ny fil at skrive videre på"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Kan ikke læse filen, der skal skrives videre på"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Kan ikke hente data fra filen, der skal skrives videre på"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Fejl under skrivning af fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Ikke understøttet (ikke samme mappe)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Ikke understøttet (kilde er mappe, destination er mappe)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Ikke understøttet (kilde er mappe, destination er eksisterende fil)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Ikke understøttet (kilde er fil, destination er mappe)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-klientfejl: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ugyldig kodning)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Mappeunderrettelse understøttes ikke"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows-netværk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Netværksstedsovervåger"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s på %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB-understøttelse mangler. Kontakt venligst din softwareforhandler"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Forbindelsen til enheden tabt"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Enheden kræver en softwareopdatering"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh-programmet afsluttede uventet"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Ukendt værtsnavn"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ingen rute til vært"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Forbindelse nægtet af server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Godkendelse af værtsnøgle slog fejl"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Kunne ikke starte ny instans af ssh-program"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Kunne ikke starte ny instans af ssh-program: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Tidsudløb ved indlogning"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Indtast adgangskode for nøgle"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Indtast kodeord"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Kan ikke sende kodeord"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Log ind alligevel"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Afbryd indlogning"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identiteten af den fjerne computer (%s) er ukendt.\n"
+"Dette sker når du logger ind på en computer første gang.\n"
+"\n"
+"Identiteten som sendes af den fjerne computer er %s. Hvis du vil være "
+"fuldstændig sikker på at det er sikkert at fortsætte, så kontakt "
+"systemadministratoren."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Logind-dialog afbrudt"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Kan ikke sende bekræftelse af værtsidentitet"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokolfejl"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp for %s på %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp på %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Kunne ikke finde en understøttet ssh-kommando"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Mislykkedes"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Ugyldigt svar modtaget"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Ugyldig icon_id \"%s\" i OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Fejl ved oprettelse af sikkerhedskopi af fil: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Kunne ikke oprette midlertidig fil"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Kan ikke flytte mappe over mappe"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Delingen %s på %s kræver et kodeord"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Intern fejl (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Kunne ikke montere Windows-deling"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Uunderstøttet søgningstype"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Oprettelse af sikkerhedskopifil mislykkedes: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Fejl ved sletning af fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Fejl ved flytning af fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Fejl ved fjernelse af destinationsfil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Kan ikke flytte mappen rekursivt"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Filsystemstjeneste for Windows-delinger"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s kræver en adgangskode"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows-delinger på %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Kunne ikke hente delingsliste fra server"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Denne fil kan ikke monteres"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ikke en regulær fil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Filsystemstjeneste til Windows-netværk"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Papirkurvsmappen kan ikke slettes"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Elementer i papirkurven kan ikke modificeres"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Papirkurv"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ugyldig backend-type"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Fejl ved afsending af fildeskriptor: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Backend understøtter ikke symbolske links"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Ugyldig dbus-meddelelse"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Erstat gammel dæmon."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Undlad at starte fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-dæmon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hoveddæmon for GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Prøv \"%s --help\" for mere information."
+
+# spawn? Det er sådan et halv-reserveret ord, en specifik OS-funktion
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Ugyldige argumenter fra spawnet underproces"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automontering mislykkedes: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Den angivne placering er ikke monteret"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Den angivne placering understøttes ikke"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Placeringen er allerede monteret"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Placeringen kan ikke monteres"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tom CD-ROM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tom CD-R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tom CD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tom DVD-ROM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Blank DVD-RAM-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tom DVD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tom DVD+R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tom DVD+RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tom DVD+R DL-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tom Blu-Ray-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tom Blu-Ray R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tom Blu-Ray RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tom HD DVD-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tom HD DVD-R-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tom HD DVD-RW-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tom MO-disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tom disk"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-drev"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-drev"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskettedrev"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Sofware-RAID-drev"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-drev"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-drev"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-drev"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire-drev"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Bånddrev"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-drev"
+
+# MemoryStick bør nok ikke oversættes da det refererer til en bestemt teknologi
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-drev"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-drev"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-drev"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-drev"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-drev"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb-drev"
+
+# wiki: "Devices which support this standard are referred to as MSC (Mass Storage Class) devices. Blahblah..."
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Mass Storage-drev"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Kunne ikke skubbe mediet ud; et eller flere drev på mediet er optaget."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Blandet lyd-/datadisk"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s-medie"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s krypteret data"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: fejl ved åbning af fil: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, skrivefejl til standard-uddata"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: læsefejl: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: fejl ved lukning: %s\n"
+
+# ??? det er nok en identifier (som det er ok at oversætte)
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "PLACERING... - sammenføj PLACERINGER til standard-uddata."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Sammenføj filer på forskellige placeringer og udskriv til standard-uddata. "
+"Virker præcis som det traditionelle cat-værktøj, men bruger gvfs-placeringer "
+"i stedet for lokale filer: for eksempel kan du skrive smb://server/resource/"
+"file.txt som placeringen der skal sammenføjes."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"NB: send dette (pipe) gennem cat hvis du skal bruge cats "
+"formatteringstilvalg såsom -n og -T."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: mangler placeringer"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: fejl ved åbning af placering: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: fejl ved programopstart: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILER... - åbn FILER med registreret program."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Åbner filen eller filerne med det forvalgte program for den pågældende "
+"filtype."
+
+#~ msgid "dns-sd"
+#~ msgstr "dsn-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (i papirkurv)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Kan ikke slette affald"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Underrettelse om papirkurvsmappe understøttes ikke"
+
+#~ msgid "File unavailable"
+#~ msgstr "Filen utilgængelig"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB-medie"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB-medie"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB-medie"
diff --git a/trunk/po/de.po b/trunk/po/de.po
new file mode 100644
index 00000000..23780548
--- /dev/null
+++ b/trunk/po/de.po
@@ -0,0 +1,1684 @@
+# German gvfs translation
+# Copyright (C) 2007 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+# Andre Klapper <ak-47@gmx.net>, 2008.
+# Hendrik Brandt <heb@gnome-de.org>, 2008.
+# Hendrik Richter <hendrikr@gnome.org>, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs trunk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-10 09:41+0100\n"
+"PO-Revision-Date: 2009-03-10 10:45+0100\n"
+"Last-Translator: Hendrik Richter <hendrikr@gnome.org>\n"
+"Language-Team: German <gnome-de@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"Vorgang wird nicht unterstützt, die Dateien liegen an verschiedenen "
+"Speicherorten"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Ungültiger Rückgabewert von get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Ungültiger Rückgabewert von query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Beschreibung des Datenstroms konnte nicht geholt werden"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Ungültiger Rückgabewert von open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Beschreibung des Datenstroms konnte nicht geholt werden"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Ungültiger Rückgabewert von call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ungültiger Rückgabewert von get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Es wurde kein gültiger Speicherort gefunden"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ungültiger Dateiname %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ungültiger Rückgabewert von query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Ungültiger Rückgabewert von monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Ungültiger Rückgabewert von monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:298
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "Vorgang wurde abgebrochen"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Fehler im Datenstromprotokoll: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Ende des Datenstroms"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "Durchsuchen im Datenstrom wird nicht unterstützt"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Fehler beim Abfragen von Informationen zum Speicherort: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Fehler beim Verbinden zum Dienst: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Ungültiger Rückgabewert von open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Fehler beim Erstellen des Socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Fehler beim Verbinden zum Socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Ungültiges Dateiinfo-Format"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Ungültiger Inhalt der Attributinfoliste"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Fehler beim Initialisieren von Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Fehler beim Erstellen des Avahi-Auflösers: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Fehler beim Auflösen des »%s«-Service »%s« auf »%s«"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Fehler beim Auflösen des »%s«-Service »%s« auf »%s«. Ein oder mehrere TXT-"
+"Einträge fehlen. Benötigte Schlüssel: »%s«."
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Zeitüberschreitung beim Auflösen des »%s«-Service »%s« auf »%s«"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Fehlerhaftes dns-sd encoded_triple »%s«"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Version %d der GVfsIcon-Kodierung kann nicht verarbeitet werden"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Fehlerhafte Eingabedaten für GVfsIcon"
+
+#: ../daemon/daemon-main.c:76 ../daemon/daemon-main.c:226
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Fehler beim Verbinden zu D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:91
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s-Dateisystem-Dienst"
+
+#: ../daemon/daemon-main.c:110
+#, c-format
+msgid "Error: %s"
+msgstr "Fehler: %s"
+
+#: ../daemon/daemon-main.c:151
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Aufruf: %s --spawner DBus-ID object_path"
+
+#: ../daemon/daemon-main.c:175 ../daemon/daemon-main.c:193
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Aufruf: %s Schlüssel=Wert Schlüssel=Wert …"
+
+#: ../daemon/daemon-main.c:191
+#, c-format
+msgid "No mount type specified"
+msgstr "Kein Mount-Typ angegeben"
+
+#: ../daemon/daemon-main.c:261
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "Speicherort für %s wird bereits verwendet"
+
+#: ../daemon/daemon-main.c:272
+msgid "error starting mount daemon"
+msgstr "Fehler beim Starten des Einhänge-Dienstes"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1912
+#, c-format
+msgid "/ on %s"
+msgstr "/ auf %s"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "No hostname specified"
+msgstr "Kein Server-Name angegeben"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Ungültige Mount-Spezifikation"
+
+#: ../daemon/gvfsbackendarchive.c:614 ../daemon/gvfsbackendarchive.c:658
+#: ../daemon/gvfsbackendarchive.c:708 ../daemon/gvfsbackendarchive.c:737
+#: ../daemon/gvfsbackendcdda.c:921 ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398 ../daemon/gvfsbackendftp.c:2264
+#: ../daemon/gvfsbackendnetwork.c:646 ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152 ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Datei existiert nicht"
+
+#: ../daemon/gvfsbackendarchive.c:622 ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1678 ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:691 ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Ordner konnte nicht geöffnet werden"
+
+#: ../daemon/gvfsbackendarchive.c:746 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Die Datei ist kein Ordner"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Brennen"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Temporärer Ordner konnte nicht erzeugt werden"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:717 ../daemon/gvfsbackendburn.c:743
+#: ../daemon/gvfsbackendburn.c:781 ../daemon/gvfsbackendburn.c:972
+#: ../daemon/gvfsbackendburn.c:1008 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Unbekannte Datei oder unbekannter Ordner"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Ordner ist nicht leer"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:904
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Datei kann nicht über einen Ordner kopiert werden"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-Ersteller"
+
+#: ../daemon/gvfsbackendburn.c:753 ../daemon/gvfsbackendburn.c:789
+#: ../daemon/gvfsbackendburn.c:924 ../daemon/gvfsbackendburn.c:986
+#: ../daemon/gvfsbackendburn.c:990 ../daemon/gvfsbackendburn.c:1000
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Datei existiert bereits"
+
+#: ../daemon/gvfsbackendburn.c:828 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Vorgang wird vom Backend nicht unterstützt"
+
+#: ../daemon/gvfsbackendburn.c:853
+msgid "No such file or directory in target path"
+msgstr "Keine solche Datei und kein solcher Ordner im Zielpfad"
+
+#: ../daemon/gvfsbackendburn.c:876 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Ordner kann nicht über einen Ordner kopiert werden"
+
+#: ../daemon/gvfsbackendburn.c:885 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Zieldatei existiert bereits"
+
+#: ../daemon/gvfsbackendburn.c:892 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Ordner kann nicht rekursiv kopiert werden"
+
+#: ../daemon/gvfsbackendburn.c:950 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Nicht unterstützt"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Keine Verbindung zum System-Bus möglich"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "libhal-Kontext konnte nicht erstellt werden"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "libhal konnte nicht initialisiert werden"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Kein Laufwerk angegeben"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Laufwerk %s konnte nicht gefunden werden"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Laufwerk %s enthält keine Audiodateien"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "CDDA-Medium in %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325 ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio-CD"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Dateisystem ist beschäftigt: %d geöffnete Datei"
+msgstr[1] "Dateisystem ist beschäftigt: %d geöffnete Dateien"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Keine Datei %s auf Laufwerk %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Fehler von »paranoia« auf Laufwerk %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Fehler beim Durchlaufen des Datenstroms auf Laufwerk %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Unbekannte Datei"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Die Datei existiert nicht oder ist kein Audiotitel"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Audio-CD-Dateisystem-Dienst"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Rechner"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Dateisystem"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Einhängbare Datei konnte nicht geöffnet werden"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1055
+#, c-format
+msgid "Internal error: %s"
+msgstr "Interner Fehler: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Datei konnte nicht eingehängt werden"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Kein Medium im Laufwerk"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Keine einhängbare Datei"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Datei konnte nicht ausgehängt werden"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Datei konnte nicht ausgeworfen werden"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-Fehler: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Antwort konnte nicht verarbeitet werden"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Leere Antwort"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Unerwartete Antwort vom Server"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Antwort ungültig"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV-Speicher"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Bitte Passwort für %s eingeben"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Bitte geben Sie das Proxy-Passwort ein"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Kein WebDAV-fähiger Speicher"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV auf %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Anfrage konnte nicht erstellt werden"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528 ../daemon/gvfsbackendsftp.c:3783
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Zieldatei existiert bereits"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2950
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "Die Datei wurde extern verändert"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "Anlegen der Sicherheitskopie fehlgeschlagen"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lokales Netzwerk"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Datei oder Ordner kann nicht überwacht werden."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Netzwerk"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Konten werden nicht unterstützt"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Verbindung wurde von Gegenstelle getrennt"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Es konnte keine Datenverbindung hergestellt werden. Wird dies eventuell von "
+"Ihrer Firewall unterbunden?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Datenverbindung geschlossen"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Vorgang fehlgeschlagen"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Der Speicherplatz auf dem Server ist aufgebraucht"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4094
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Vorgang wird nicht unterstützt"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Zugriff verweigert"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Unbekannter Seitentyp"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "Ungültiger Dateiname"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "Ungültige Antwort"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "beschädigte Übertragung"
+
+#: ../daemon/gvfsbackendftp.c:713 ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "Keine Verbindung zum Zielrechner möglich"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Bitte Passwort für FTP als %s auf %s eingeben"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Bitte Passwort für FTP auf %s eingeben"
+
+#: ../daemon/gvfsbackendftp.c:1525 ../daemon/gvfsbackendsftp.c:877
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Passwortdialog abgebrochen"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "FTP auf %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "FTP als %s auf %s"
+
+#: ../daemon/gvfsbackendftp.c:1692 ../daemon/gvfsbackendsftp.c:1976
+#: ../daemon/gvfsbackendsftp.c:3774
+msgid "File is directory"
+msgstr "Datei ist ein Ordner"
+
+#: ../daemon/gvfsbackendftp.c:1914 ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2811
+msgid "backups not supported yet"
+msgstr "Sicherheitskopien werden derzeit nicht unterstützt"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "Dateiname ist zu lang"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "Ungültiger Zieldateiname"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Ordner oder Datei existiert bereits"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Unbekannte Datei oder unbekannter Ordner"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ungültiger Dateiname"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nicht unterstützt"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalkamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s Kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s Musik-Player"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Musik-Player"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Kein Gerät angegeben"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2-Kontext konnte nicht erstellt werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Fehler beim Erstellen der Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Fehler beim Laden der Geräteinformationen"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Fehler beim Nachschlagen der Geräteinformationen"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Fehler beim Abrufen der Geräteinformationen"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Fehler beim Einrichten des Kamera-Kommunikationsports"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Fehler beim Initialisieren der Kamera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2-Medium auf %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Keine Kamera angegeben"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Fehler beim Anlegen des Dateiobjekts"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Fehler beim Abrufen der Datei"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Fehler beim Auslesen der Datei"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Fehlerhafte Symbolidentifikation »%s«"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Fehler beim Durchlaufen des Datenstroms auf Kamera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Kein Ordner"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Ordnerliste konnte nicht abgerufen werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Dateiliste konnte nicht abgerufen werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Fehler beim Erstellen des Ordners"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Name existiert bereits"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Neuer Dateiname ist zu lang"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Fehler beim Umbenennen des Ordners"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Fehler beim Umbenennen der Datei"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Ordner »%s« ist nicht leer"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Fehler beim Löschen des Ordners"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Fehler beim Löschen der Datei"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "In Ordner konnte nicht geschrieben werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Zu schreibende Datei konnte nicht reserviert werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Zu schreibende Datei konnte nicht gelesen werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Zu schreibende Datei konnte nicht ausgelesen werden"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Fehler beim Schreiben der Datei"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Nicht unterstützt (nicht der selbe Ordner)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nicht unterstützt (Quelle und Ziel sind Ordner)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+"Nicht unterstützt (Quelle ist Ordner, Ziel ist bereits existierende Datei)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nicht unterstützt (Quelle ist Datei, Ziel ist Ordner)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-Client-Fehler: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1900
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ungültige Kodierung)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Ordnerbenachrichtigung wird nicht unterstützt"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows-Netzwerk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Rechner im Netzwerk"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s auf %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+"USB-Unterstützung fehlt. Bitten wenden Sie sich an Ihren Software-Hersteller"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Verbindung zum Gerät getrennt"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Gerät benötigt eine Aktualisierung der Software"
+
+#: ../daemon/gvfsbackendsftp.c:291
+msgid "ssh program unexpectedly exited"
+msgstr "Das SSH-Programm wurde unerwartet beendet"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Unbekannter Server-Name"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "Keine Verbindung zum Server"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "Verbindung wurde vom Server verweigert"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Überprüfung des Server-Schlüssels fehlgeschlagen"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "Das SSH-Programm konnte nicht gestartet werden"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Das SSH-Programm konnte nicht gestartet werden: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:783
+msgid "Timed out when logging in"
+msgstr "Zeitüberschreitung beim Anmelden"
+
+#: ../daemon/gvfsbackendsftp.c:861
+msgid "Enter passphrase for key"
+msgstr "Bitte geben Sie das Passwort für den Schlüssel ein"
+
+#: ../daemon/gvfsbackendsftp.c:863
+msgid "Enter password"
+msgstr "Passwort eingeben"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send password"
+msgstr "Passwort kann nicht gesendet werden"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Log In Anyway"
+msgstr "Dennoch anmelden"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Cancel Login"
+msgstr "Anmelden abbrechen"
+
+#: ../daemon/gvfsbackendsftp.c:957
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Die Identität des entfernten Rechners (%s) ist unbekannt.\n"
+"Dies ist der Fall, wenn Sie sich das erste Mal an einem Rechner anmelden.\n"
+"\n"
+"Die vom entfernten Rechner übermittelte Identität ist %s. Wenn Sie vor dem "
+"Fortfahren absolut sicher gehen wollen, dann kontaktieren Sie Ihren "
+"Systemadministrator."
+
+#: ../daemon/gvfsbackendsftp.c:977
+msgid "Login dialog cancelled"
+msgstr "Anmeldedialog abgebrochen"
+
+#: ../daemon/gvfsbackendsftp.c:997
+msgid "Can't send host identity confirmation"
+msgstr "Identitätsbestätigung konnte nicht gesendet werden"
+
+#: ../daemon/gvfsbackendsftp.c:1490 ../daemon/gvfsbackendsftp.c:1513
+msgid "Protocol error"
+msgstr "Protokollfehler"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1538
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "SFTP als %s auf %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1541
+#, c-format
+msgid "sftp on %s"
+msgstr "SFTP auf %s"
+
+#: ../daemon/gvfsbackendsftp.c:1567
+msgid "Unable to find supported ssh command"
+msgstr "Es konnte kein unterstütztes SSH-Programm gefunden werden"
+
+#: ../daemon/gvfsbackendsftp.c:1985
+msgid "Failure"
+msgstr "Fehler"
+
+#: ../daemon/gvfsbackendsftp.c:2041 ../daemon/gvfsbackendsftp.c:2120
+#: ../daemon/gvfsbackendsftp.c:2131 ../daemon/gvfsbackendsftp.c:2187
+#: ../daemon/gvfsbackendsftp.c:2273 ../daemon/gvfsbackendsftp.c:2323
+#: ../daemon/gvfsbackendsftp.c:2369 ../daemon/gvfsbackendsftp.c:2444
+#: ../daemon/gvfsbackendsftp.c:2551 ../daemon/gvfsbackendsftp.c:2591
+#: ../daemon/gvfsbackendsftp.c:2641 ../daemon/gvfsbackendsftp.c:2713
+#: ../daemon/gvfsbackendsftp.c:2725 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2825 ../daemon/gvfsbackendsftp.c:3002
+#: ../daemon/gvfsbackendsftp.c:3027 ../daemon/gvfsbackendsftp.c:3082
+#: ../daemon/gvfsbackendsftp.c:3139 ../daemon/gvfsbackendsftp.c:3410
+#: ../daemon/gvfsbackendsftp.c:3477 ../daemon/gvfsbackendsftp.c:3612
+#: ../daemon/gvfsbackendsftp.c:3672 ../daemon/gvfsbackendsftp.c:3707
+#: ../daemon/gvfsbackendsftp.c:3735 ../daemon/gvfsbackendsftp.c:3843
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3933
+#: ../daemon/gvfsbackendsftp.c:3967 ../daemon/gvfsbackendsftp.c:3982
+#: ../daemon/gvfsbackendsftp.c:3997 ../daemon/gvfsbackendsftp.c:4075
+msgid "Invalid reply received"
+msgstr "Ungültige Antwort erhalten"
+
+#: ../daemon/gvfsbackendsftp.c:2093
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Ungültige icon_id »%s« in OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2389
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Fehler beim Anlegen der Sicherheitskopie: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2887
+msgid "Unable to create temporary file"
+msgstr "Temporäre Datei konnte nicht erzeugt werden"
+
+#: ../daemon/gvfsbackendsftp.c:3769 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "Ordner kann nicht über einen Ordner verschoben werden"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Für den Speicherort %s auf %s wird ein Passwort benötigt"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Interner Fehler (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Einhängen des Windows-Speichers fehlgeschlagen"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Nicht unterstützter Suchtyp"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Anlegen der Sicherheitskopie fehlgeschlagen: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Fehler beim Löschen der Datei: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Fehler beim Verschieben der Datei: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Fehler beim Löschen der Zieldatei: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "Ordner kann nicht rekursiv verschoben werden"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows-Speicher-Dateisystem-Dienst"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Für %s wird ein Passwort benötigt"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows-Speicher auf %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Empfangen der Speicherliste vom Server ist gescheitert"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Die Datei ist nicht einhängbar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Keine gültige Datei"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows-Netzwerk-Dateisystem-Dienst"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Der Mülleimer-Ordner darf nicht gelöscht werden"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Objekte im Mülleimer dürfen nicht geändert werden"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Müll"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ungültiger Backend-Typ"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Fehler beim Senden von fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Verknüpfungen werden vom Backend nicht unterstützt"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Ungültige DBus-Nachricht"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Alten Dienst ersetzen."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "FUSE nicht starten."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-Dienst"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hauptdienst für GVFS."
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Versuchen Sie »%s --help« für mehr Informationen"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Ungültige Argumente vom erzeugten Kindprozess"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatisches Einhängen gescheitert: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Der angegebene Ort ist nicht eingehängt"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Der angegebene Ort wird nicht unterstützt"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Ort ist bereits eingehängt"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Ort kann nicht eingehängt werden"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Leere CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Leere CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Leere CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Leere DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Leere DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Leere DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Leere DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Leere DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Leere DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Leere Blu-Ray-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray-R-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Leere Blu-Ray-R-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray-RW-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Leere Blu-Ray-RW-Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD-DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Leere HD-DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD-DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Leere HD-DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Leere HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO-Medium"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Leeres MO-Medium"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Medium"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Leeres Medium"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s-/%s-Laufwerk"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "%s-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "Diskettenlaufwerk"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "Software-RAID-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "USB-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "ATA-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "SCSI-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "FireWire-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "Bandlaufwerk"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Zip-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Jaz-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "USB-Stick"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "Massenspeicher-Laufwerk"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Medium konnte nicht ausgeworfen werden. Ein oder mehr Speicherorte auf dem "
+"Medium sind noch aktiv."
+
+#: ../monitor/hal/ghalmount.c:159 ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f KB"
+
+#: ../monitor/hal/ghalmount.c:164 ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:169 ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:323 ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "Gemischtes Audio- und Daten-Medium"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336 ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "%s Medium"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s Verschlüsselte Daten"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: Fehler beim Öffnen der Datei: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s: Fehler beim Schreiben auf die Standardausgabe"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: Fehler beim Lesen: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:Fehler beim Schließen: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "ORT … ‒ aneinanderhängen der ORTE auf der Standardausgabe."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Verbindet die über ihre Orte angegebenen Dateien und gibt sie auf der "
+"Standardausgabe aus. Die Funktionsweise ist vergleichbar mit der des "
+"herkömmlichen cat-Programms, jedoch werden gvfs-Orte statt lokaler Dateien "
+"verwendet; z.B. können Sie als Ort etwas wie »smb://server/ressource/datei."
+"txt« angeben."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Hinweis: Verwenden Sie »cat«, falls Sie dessen Formatierungsoptionen wie z.B. "
+"»-n«, »-T« oder andere benötigen."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: keine Orte angegeben"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: Fehler beim Öffnen des Ortes: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: Fehler beim Starten der Anwendung: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "DATEIEN … ‒ DATEIEN mit der empfohlenen Anwendung öffnen."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Öffnet die Dateien mit der Anwendung, die als Standard für diesen Dateityp "
+"eingestellt ist."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "Das Abfragen von Informationen wird nicht unterstützt"
+
+#~ msgid "Query info not supported on stream"
+#~ msgstr "Das Abfragen von Informationen im Datenstrom wird nicht unterstützt"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (im Müll)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Der Müll kann nicht gelöscht werden"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Benachrichtigung des Müllordners wird nicht unterstützt"
+
+#~ msgid "File unavailable"
+#~ msgstr "Datei nicht verfügbar"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1fKB-Medium"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1fMB-Medium"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1fGB-Medium"
diff --git a/trunk/po/el.po b/trunk/po/el.po
new file mode 100644
index 00000000..ccf10e67
--- /dev/null
+++ b/trunk/po/el.po
@@ -0,0 +1,1853 @@
+# translation of el.po to Greek
+# Simos Xenitellis <simos@gnome.org>, 2008.
+# Kostas Papadimas <pkst@gnome.org>, 2008.
+# translation of gvfs to Greek
+msgid ""
+msgstr ""
+"Project-Id-Version: el\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-01-06 15:17+0000\n"
+"PO-Revision-Date: 2009-01-27 00:35+0200\n"
+"Last-Translator: nikosCharonitakis <nikosx@gmail.com>\n"
+"Language-Team: Greek <team@gnome.gr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Δεν υποστηρίζεται η λειτουργία διότι τα αρχεία βρίσκονται σε διαφορετικές προσαρτήσεις"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Μη έγκυρη απάντηση από get_info"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Μη έγκυρη απάντηση από query_info"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Αδύνατη η λήψη περιγραφέα αρχείου stream"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Μη έγκυρη απάντηση από open"
+
+#
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Αδύνατη η λήψη περιγραφέα αρχείου stream"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Μη έγκυρη τιμή επιστροφής από call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Μη έγκυρη τιμή επιστροφής από get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Αδυναμία εύρεσης εσώκλειστης προσάρτησης"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ακατάλληλο όνομα αρχείου %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Μη έγκυρη τιμή επιστροφής από query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Μη έγκυρη τιμή επιστροφής απόmonitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Μη έγκυρη τιμή επιστροφής από monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:741
+#: ../daemon/gvfsbackendobexftp.c:762
+#: ../daemon/gvfsbackendobexftp.c:881
+#: ../daemon/gvfsbackendobexftp.c:1018
+#: ../daemon/gvfsbackendobexftp.c:1082
+#: ../daemon/gvfsbackendobexftp.c:1219
+#: ../daemon/gvfsbackendobexftp.c:1246
+#: ../daemon/gvfsbackendobexftp.c:1305
+#: ../daemon/gvfsbackendobexftp.c:1327
+#: ../daemon/gvfsbackendobexftp.c:1387
+#: ../daemon/gvfsbackendobexftp.c:1406
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Η λειτουργία ακυρώθηκε"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Σφάλμα στο πρωτόκολλο stream: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Τέλος stream"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Η αναζήτηση δεν υποστηρίζεται στο stream"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Η λειτουργία ερωτήματος πληροφοριών δεν υποστηρίζεται"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Η αναζήτηση δεν υποστηρίζεται στη ροή δεδομένων"
+
+# gconf/gconftool.c:964 gconf/gconftool.c:1070
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Σφάλμα στην λήψη mount info: %s"
+
+#: ../client/gvfsdaemondbus.c:568
+#: ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Σφάλμα κατά τη σύνδεση με την υπηρεσία: %s"
+
+#: ../client/gvfsiconloadable.c:145
+#, fuzzy
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Μη έγκυρη απάντηση από get_info"
+
+# gconf/gconfd.c:1676
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Σφάλμα δημιουργίας υποδοχέα: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Σφάλμα κατά τη σύνδεση με υποδοχέα: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Μη έγκυρος τύπος πληροφοριών αρχείου"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Μη έγκυρο γνώρισμα περιεχόμενου λίστας πληροφοριών"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Σφάλμα αρχικοποίησης Avahi: %s"
+
+# gconf/gconfd.c:1676
+#: ../common/gvfsdnssdresolver.c:254
+#, fuzzy, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Σφάλμα δημιουργίας υποδοχέα: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr ""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr ""
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Σφάλμα κατά τη σύνδεση με το D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Υπηρεσία συστήματος αρχείων %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Σφάλμα: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Χρήση: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Χρήση: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Δεν έχει οριστεί είδος προσάρτησης"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "το σημείο προσάρτησης για το %s εκτελείται ήδη"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "Σφάλμα εκκίνησης mount daemon"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ στο %s"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Δεν έχει οριστεί όνομα συστήματος"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:561
+#: ../daemon/gvfsbackendobexftp.c:572
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Μη έγκυρη προδιαγραφή προσάρτησης"
+
+#
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:2262
+#: ../daemon/gvfsbackendnetwork.c:650
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Το αρχείο δεν υπάρχει"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:440
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:697
+msgid "The file is not a directory"
+msgstr "Το αρχείο δεν είναι κατάλογος"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Γράψιμο"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Αποτυχία δημιουργίας προσωρινού καταλόγου"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:214
+#, c-format
+msgid "No such file or directory"
+msgstr "Δεν υπάρχει τέτοιο αρχείο ή κατάλογος"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Ο κατάλογος δεν είναι άδειος"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "Αδυναμία αντιγραφής αρχείου πάνω σε κατάλογο"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD Creator"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Το αρχείο υπάρχει"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Δεν υποστηρίζεται η λειτουργία από το backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Δεν υπάρχει τέτοιο αρχείο ή κατάλογος στη διαδρομή προορισμού"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "Δεν είναι δυνατή η αντιγραφή καταλόγου πάνω σε κατάλογο"
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "Το τελικό αρχείο υπάρχει ήδη"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "Δεν είναι δυνατή η αντιγραφή καταλόγου recursive"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281
+#: ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587
+#: ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Δεν υποστηρίζεται"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Αδυναμία σύνδεσης στο διάδρομο συστήματος"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Αδυναμία δημιουργίας περιεχομένου libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Αδυναμία αρχικοποίησης libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Δεν έχει καθορισθεί συσκευή"
+
+# backends/xml-backend.c:315
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Αδυναμία εύρεσης συσκευής %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Η συσκευή '%s' δεν περιέχει αρχεία ήχου"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "προσάρτηση cdda σε %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Δίσκος Audio"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Το σύστημα αρχείων είναι απασχολημένο: %d ανοικτό αρχείο"
+msgstr[1] "Το σύστημα αρχείων είναι απασχολημένο: %d ανοικτά αρχεία"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Δεν υπάρχει αρχείο %s στον οδηγό %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Σφάλμα από 'paranoia' στο δίσκο %s"
+
+#
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Σφάλμα ανάγνωσης στο δίσκο %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Δεν υπάρχει τέτοιο αρχείο"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Το αρχείο δεν υπάρχει ή δεν είναι ένα ηχητικό κομμάτι"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Υπηρεσία συστήματος αρχείων Audio CD "
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Υπολογιστής"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Σύστημα αρχείων"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:727
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:230
+#, c-format
+msgid "Can't open directory"
+msgstr "Αδυναμία ανοίγματος καταλόγου"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Αδυναμία ανοίγματος του προσαρτημένου αρχείου "
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Εσωτερικό σφάλμα: %s"
+
+# gconf/gconf-internals.c:2404
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Αδυναμία προσάρτησης αρχείου"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Δεν υπάρχει μέσο στη συσσκευή"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Δεν είναι προσαρτήσιμο αρχείο"
+
+# gconf/gconf-internals.c:2404
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Αδυναμία αποπροσάρτησης αρχείου"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Αδυναμία αποβολής αρχείου"
+
+#: ../daemon/gvfsbackenddav.c:526
+#: ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Σφάλμα HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Αδύνατη η συντακτική ανάλυση απόκρισης"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Κενή απόκριση"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Απροσδόκητη απάντηση από διακομιστή"
+
+#: ../daemon/gvfsbackenddav.c:1179
+#: ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Μη έγκυρη απόκριση"
+
+#
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Διαμοίρασμα WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Εισάγετε κωδικό για %s"
+
+#
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Παρακαλώ εισάγετε τον κωδικό διαμεσολαβητή"
+
+#: ../daemon/gvfsbackenddav.c:1662
+#: ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Δεν είναι μια ενεργοποιημένη WebDAV share"
+
+#
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV στο %s"
+
+#: ../daemon/gvfsbackenddav.c:1754
+#: ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Δεν ήταν δυνατή η δημιουργία αίτησης"
+
+#: ../daemon/gvfsbackenddav.c:1890
+#: ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254
+#: ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Το αρχείο προορισμού υπάρχει ήδη"
+
+#: ../daemon/gvfsbackenddav.c:1963
+#: ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Το αρχείο τροποποιήθηκε εξωτερικά"
+
+#: ../daemon/gvfsbackenddav.c:1994
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Απέτυχε η δημιουργία αντιγράφου ασφαλείας"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:487
+#: ../daemon/gvfsbackendnetwork.c:397
+msgid "Local Network"
+msgstr "Τοπικό δίκτυο"
+
+#: ../daemon/gvfsbackenddnssd.c:731
+#: ../daemon/gvfsbackendnetwork.c:801
+msgid "Can't monitor file or directory."
+msgstr "Αδυναμία παρακολούθησης αρχείου ή καταλόγου"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:749
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:750
+#: ../daemon/gvfsbackendnetwork.c:736
+#: ../daemon/gvfsbackendnetwork.c:886
+#: ../daemon/gvfsbackendnetwork.c:887
+msgid "Network"
+msgstr "Δίκτυο"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Δεν υποστηρίζονται λογαριασμοί"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Το σύστημα έκλεισε τη σύνδεση"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Αδυναμία ανοίγματος σύνδεσης δεδομένων. Μήπως ο firewall σας την εμποδίζει;"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Η σύνδεση δεδομένων έκλεισε"
+
+#: ../daemon/gvfsbackendftp.c:271
+#: ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Αποτυχία λειτουργίας"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Δεν απέμεινε ελεύθερος χώρος στον εξυπηρετητή"
+
+#: ../daemon/gvfsbackendftp.c:288
+#: ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Δεν υποστηρίζεται η λειτουργία"
+
+#: ../daemon/gvfsbackendftp.c:292
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Δεν επιτρέπεται η πρόσβαση"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Άγνωστος τύπος σελίδας"
+
+#: ../daemon/gvfsbackendftp.c:300
+#: ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Μη έγκυρο όνομα αρχείου"
+
+#: ../daemon/gvfsbackendftp.c:304
+#: ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Μη έγκυρη απάντηση"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "προβληματική μετάδοση"
+
+#: ../daemon/gvfsbackendftp.c:710
+#: ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Δεν ήταν δυνατή η σύνδεση στο σύστημα"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Εισάγετε κωδικό πρόσβασης για ftp ως %s στο %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Εισάγετε κωδικό για ftp σε %s"
+
+# #-#-#-#-# gdm.gnome-2-20.el.po (el) #-#-#-#-#
+#
+#: ../daemon/gvfsbackendftp.c:1523
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Ο διάλογος κωδικού ακυρώθηκε"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp στο %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp ως %s στο %s"
+
+#: ../daemon/gvfsbackendftp.c:1690
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Το αρχείο είναι κατάλογος"
+
+#: ../daemon/gvfsbackendftp.c:1912
+#: ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "τα αντίγραφα ασφαλείας δεν υποστηρίζονται ακόμα"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "το όνομα αρχείου είναι πολύ μεγάλο"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Ακατάλληλο όνομα αρχείου προορισμού"
+
+#
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Ο κατάλογος ή αρχείο υπάρχει"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Δεν υπάρχει τέτοιο αρχείο ή κατάλογος"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Μη έγκυρο όνομα αρχείου"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Δεν υποστηρίζεται"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Ψηφιακή κάμερα (%s)"
+
+# #-#-#-#-# gnome-icon-theme.HEAD.el.po (el) #-#-#-#-#
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823
+#: ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Φωτογραφική μηχανή %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826
+#: ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s Audio Player"
+
+# #-#-#-#-# gnome-icon-theme.HEAD.el.po (el) #-#-#-#-#
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Φωτογραφική μηχανή"
+
+#: ../daemon/gvfsbackendgphoto2.c:837
+#: ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Audio Player"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Δεν έχει καθορισθεί συσκευή"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Αδυναμία δημιουργίας περιεχομένου gphoto2"
+
+# gconf/gconfd.c:1676
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Σφάλμα δημιουργίας κάμερας"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383
+#: ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Σφάλμα φόρτωσης πληροφοριών συσκευής"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Σφάλμα αναζήτησης πληροφοριών συσκευής"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Σφάλμα λήψης πληροφοριών συσκευής"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Σφάλμα εγκατάστασης θύρας επικοινωνίας της κάμερας"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Σφάλμα αρχικοποίησης κάμερας"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "προσάρτηση gphoto2 σε %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Δεν έχει καθοριστεί κάμερα"
+
+# gconf/gconftool.c:1181
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Σφάλμα δημιουργίας του αντικειμένου του αρχείου"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Σφάλμα λήψης αρχείου"
+
+#
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Σφάλμα λήψης δεδομένων από αρχείο"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr ""
+
+#
+#: ../daemon/gvfsbackendgphoto2.c:1772
+#: ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Σφάλμα αναζήτησης στη ροή δεδομένων της κάμερας %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Δεν είναι κατάλογος"
+
+#
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Αποτυχία λήψης λίστας φακέλων"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Αποτυχία λήψης λίστας αρχείων"
+
+# gconf/gconfd.c:1676
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Σφάλμα δημιουργίας καταλόγου"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Το όνομα υπάρχει ήδη"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513
+#: ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Το νέο όνομα είναι πολύ μακρύ"
+
+# gconf/gconftool.c:982 gconf/gconftool.c:1084
+#: ../daemon/gvfsbackendgphoto2.c:2523
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Σφάλμα μετονομασίας καταλόγου"
+
+#
+#: ../daemon/gvfsbackendgphoto2.c:2536
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Σφάλμα μετονομασίας αρχείου"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Ο κατάλογος '%s' δεν είναι άδειος"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Σφάλμα διαγραφής καταλόγου"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Σφάλμα διαγραφής αρχείου"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Αδυναμία εγγραφής σε κατάλογο"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Αδυναμία διάθεσης νέου αρχείου για προσθήκη σε αυτό"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Αδυναμία ανάγνωσης αρχείου για προσθήκη σε αυτό"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Αδυναμία λήψης δεδομένων του αρχείου για προσθήκη σε αυτό"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Σφάλμα εγγραφής αρχείου"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Δεν υποστηρίζεται (δεν είναι ο ίδιος κατάλογος)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Δεν υποστηρίζεται (το src είναι κατάλογος, το dst είναι κατάλογος)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Δεν υποστηρίζεται (το src is κατάλογος, το dst είναι υπάρχον αρχείο)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Δεν υποστηρίζεται (το src είναι αρχείο, το dst είναι κατάλογος)"
+
+# gconf/gconftool.c:951
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Σφάλμα πελάτη HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (μη έγκυρη κωδικοποίηση)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Η ειδοποίηση καταλόγου δεν υποστηρίζεται"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Δίκτυο Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:935
+msgid "Network Location Monitor"
+msgstr "Παρακολούθηση τοποθεσίας δικτύου"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:387
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s σε %s"
+
+#: ../daemon/gvfsbackendobexftp.c:666
+msgid "Connection to the device lost"
+msgstr "Η σύνδεση στη συσκευή χάθηκε"
+
+#: ../daemon/gvfsbackendobexftp.c:1163
+msgid "Device requires a software update"
+msgstr "Η συσκευή χρειάζεται μια ενημέρωση του λογισμικού"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "απρόσμενη έξοδος προγράμματος ssh"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Άγνωστο όνομα συστήματος"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Δεν υπάρχει διαδρομή προς το σύστημα"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Έγινε άρνηση σύνδεσης από τον εξυπηρετητή"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Αποτυχία πιστοποίησης κλειδιού host"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Αδυναμία spawn προγράμματος ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Αδυναμία spawn προγράμματος ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Λήξη χρόνου στην είσοδο"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Εισαγωγή συνθηματικού για κλειδί"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Εισαγωγή κωδικού"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Αδυναμία αποστολής κωδικού"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Είσοδος οπωσδήποτε"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Ακύρωση εισόδου"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Η ταυτότητα του απομακρυσμένου υπολογιστή (%s) είναι άγνωστη.\n"
+"Αυτό συμβαίνει όταν συνδέεστε για πρώτη φορά σε έναν υπολογιστή.\n"
+"\n"
+"Η ταυτότητα που στάλθηκε από τον απομακρυσμένο υπολογιστή είναι %s.Αν είστε απόλυτα σίγουροι ότι είναι ασφαλές να συνεχίσετε, επικοινωνήστε με τον διαχειριστή του συστήματος."
+
+# #-#-#-#-# gdm.gnome-2-20.el.po (el) #-#-#-#-#
+#
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Ο διάλογος εισόδου ακυρώθηκε"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Αδυναμία αποστολής επιβεβαίωσης ταυτότητας συστήματος"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Σφάλμα πρωτοκόλου"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp για %s στο %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp στο %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Αδυναμία εύρεσης υποστηριζόμενης εντολής ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Αποτυχία"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721
+#: ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898
+#: ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010
+#: ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348
+#: ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512
+#: ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648
+#: ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736
+#: ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785
+#: ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Λήφθηκε μη έγκυρη απάντηση"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr ""
+
+# gconf/gconftool.c:1181
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Σφάλμα δημιουργίας αντιγράφου ασφαλείας: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Αδυναμία δημιουργίας προσωρινού φακέλου"
+
+#: ../daemon/gvfsbackendsftp.c:3574
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Δεν είναι δυνατή η μετακίνηση καταλόγου σε κατάλογο"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Απαιτείται κωδικός για το κοινόχρηστο %s σε %s"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Εσωτερικό σφάλμα (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Αποτυχία προσάρτησης διαμοιραζόμενου Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Μη υποστηριζόμενος τύπος seek"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Αποτυχία δημιουργίας αρχείου αντιγράφου ασφαλείας: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Σφάλμα διαγραφής αρχείου: %s"
+
+#
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Σφάλμα μετακίνησης αρχείου: %s"
+
+#
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Σφάλμα απομάκρυνσης αρχείου προορισμού: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Δεν είναι δυνατή η recursive μετακίνηση καταλόγου"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Υπηρεσία συστήματος αρχείων Windows Shares"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Απαιτείται κωδικός για το %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Διαμοιραζόμενοι πόροι Windows στο %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Το αρχείο δε μπορεί να προσαρτηθεί"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Δεν είναι τυπικό αρχείο"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Υπηρεσία συστήματος αρχείων δκτύου Windows"
+
+#: ../daemon/gvfsbackendtrash.c:344
+#, c-format
+msgid "Can't delete trash"
+msgstr "Αδυναμία διαγραφής των απορριμμάτων"
+
+#: ../daemon/gvfsbackendtrash.c:361
+#: ../daemon/gvfsbackendtrash.c:413
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:399
+#, fuzzy, c-format
+msgid "Can't pull trash"
+msgstr "Αδυναμία διαγραφής των απορριμμάτων"
+
+# #-#-#-#-# nautilus.HEAD.el.po (el) #-#-#-#-#
+# #-#-#-#-# user-guide.HEAD.el.po (user-guide.docs) #-#-#-#-#
+# #-#-#-#-# nautilus.HEAD.el.po (el) #-#-#-#-#
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:708
+#: ../daemon/gvfsbackendtrash.c:816
+msgid "Trash"
+msgstr "Απορρίμματα"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Μη έγκυρος τύπος backend"
+
+# gconf/gconftool.c:982 gconf/gconftool.c:1084
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Σφάλμα αποστολής fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Οι συμβολικοί δεσμοί δεν υποστηρίζονται από το backend"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Μη έγκυρο μήνυμα dbus"
+
+#
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Αντικατάσταση παλιάς υπηρεσίας."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Να μην γίνει εκκίνηση της υπηρεσίας fuse."
+
+#
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Υπηρεσία GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Κύρια υπηρεσία για GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Εκτελέστε \"%s --help\" για περισσότερες πληροφορίες."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Μη έγκυρες παράμετροι από spawned child"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Αποτυχία αυτόματης προσάρτησης: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Η καθορισμένη τοποθεσία δεν έχει προσαρτηθεί"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Η καθορισμένη τοποθεσία δεν υποστηρίζεται"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Η τοποθεσία είναι ήδη προσαρτημένη"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Η τοποθεσία δεν μπορεί να προσαρτηθεί"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Δίσκος CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Κενός δίσκος CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Δίσκος CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Κενός δίσκος CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Δίσκος CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Κενός δίσκος CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Δίσκος DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Κενός δίσκος DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Δίσκος DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Κενός δίσκος DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Δίσκος DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Κενός δίσκος DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Δίσκος DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Κενός δίσκος DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Δίσκος DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Κενός δίσκος DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Δίσκος DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Κενός δίσκος DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Δίσκος Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Κενός δίσκος Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Δίσκος Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Κενός δίσκος Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Δίσκος Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Κενός δίσκος Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Δίσκος HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Κενός δίσκος HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Δίσκος HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Κενός δίσκος HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Δίσκος HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Κενός δίσκος HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Δίσκος ΜΟ"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Κενός δίσκος ΜΟ"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Δίσκος"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Κενός δίσκος"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Συσκευή %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Συσκευή %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Συσκευή δισκέτας"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Συσκευή RAID λογισμικού"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Συσκευή USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Συσκευή ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Συσκευή SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Συσκευή FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Συσκευή ταινίας"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Συσκευή CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Συσκευή Memory Stick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Συσκευή Smart Media"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Συσκευή SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Συσκευή zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Συσκευή Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Συσκευή Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Συσκευή μαζικής αποθήκευσης"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Αποτυχία αποβολής μέσου. Ένας ή περισσότεροι τόμοι είναι απασχολημένοι"
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GΒ"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Μικτός δίσκος ήχου/δεδομένων"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Δεδομένα %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Κρυπτογραφημένα δεδομένα %s"
+
+#
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: σφάλμα κατά το άνοιγμα αρχείου: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, σφάλμα εγγραφής στην κανονική έξοδο"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: σφάλμα κατά την ανάγνωση: %s\n"
+
+#
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:σφάλμα κλεισίματος: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - σύνδεση ΤΟΠΟΘΕΣΙΩΝ στην στάνταρ έξοδο."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Σύνδεση αρχείων σε τοποθεσίες και εκτύπωση στην στάνταρ έξοδο. Λειτουργεί όπως το παραδοσιακό εργαλείο Cat, αλλά χρησιμοποιεί την τοποθεσία gvfs αντί για τα τοπικά αρχεία: Για παράδειγμα μπορείτε να χρησιμοποιήσετε κάτι σαν smb://server/resource/file.txt ως τοποθεσία για σύνδεση."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: λείπουν τοποθεσίες"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: Σφάλμα ανοίγματος τοποθεσίας: %s\n"
+
+# gconf/gconftool.c:1181
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: Σφάλμα εκκίνησης εφαρμογής: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - άνοιγμα ΑΡΧΕΙΩΝ με την καθορισμένη εφαρμογή."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Ανοίγει τα αρχεία με την προεπιλεγμένη εφαρμογή που έχει ορισθεί να χειρίζεται αυτούς τους τύπους αρχείων."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (στα απορρίμματα)"
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Η ειδοποίηση κατάλογου απορριμμάτων δεν υποστηρίζεται"
+#~ msgid "File unavailable"
+#~ msgstr "Μη διαθέσιμο αρχείο"
+#~ msgid "%.1f kB Media"
+#~ msgstr "Δεδομένα %.1f kB"
+#~ msgid "%.1f MB Media"
+#~ msgstr "Δεδομένα %.1f MB"
+#~ msgid "%.1f GB Media"
+#~ msgstr "Δεδομένα %.1f GB"
+
diff --git a/trunk/po/en_GB.po b/trunk/po/en_GB.po
new file mode 100644
index 00000000..7128dce6
--- /dev/null
+++ b/trunk/po/en_GB.po
@@ -0,0 +1,1652 @@
+# English (British) translation.
+# Copyright (C) 2008 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gvfs package.
+#
+#
+# Philip Withnall <pwithnall@svn.gnome.org>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-23 18:23+0000\n"
+"PO-Revision-Date: 2009-02-23 18:27+0000\n"
+"Last-Translator: Philip Withnall <pwithnall@svn.gnome.org>\n"
+"Language-Team: <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operation not supported, files on different mounts"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Invalid return value from get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Invalid return value from query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Couldn't get stream file descriptor"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Invalid return value from open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Didn't get stream file descriptor"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Invalid return value from call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Invalid return value from get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Could not find enclosing mount"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Invalid filename %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Invalid return value from query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Invalid return value from monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Invalid return value from monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operation was cancelled"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Error in stream protocol: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "End of stream"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Seek not supported on stream"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "The query info operation is not supported"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Query info not supported on stream"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Error while getting mount info: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Error connecting to daemon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Invalid return value from open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Error creating socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Error connecting to socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Invalid file info format"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Invalid attribute info list content"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Error initialising Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Error creating Avahi resolver: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Malformed DNS-SD encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Can't handle version %d of GVfsIcon encoding"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Malformed input data for GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Error connecting to D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s Filesystem Service"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Error: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Usage: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Usage: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "No mount type specified"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "mountpoint for %s already running"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "error starting mount daemon"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ on %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "No hostname specified"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Invalid mount spec"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "File doesn't exist"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "The file is not a directory"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Burn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Unable to create temporary directory"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "No such file or directory"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Directory not empty"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Can't copy file over directory"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD Creator"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "File exists"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operation not supported by backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "No such file or directory in target path"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Can't copy directory over directory"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Target file exists"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Can't recursively copy directory"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Not supported"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Cannot connect to the system bus"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Cannot create libhal context"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Cannot initialise libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "No drive specified"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Cannot find drive %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Drive %s does not contain audio files"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda mount on %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio Disc"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "File system is busy: %d open file"
+msgstr[1] "File system is busy: %d open files"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "No such file %s on drive %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Error from 'paranoia' on drive %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Error seeking in stream on drive %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "No such file"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "The file does not exist or isn't an audio track"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Audio CD Filesystem Service"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Filesystem"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Can't open directory"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Can't open mountable file"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Internal error: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Can't mount file"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "No media in the drive"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Not a mountable file"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Can't unmount file"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Can't eject file"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP Error: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Could not parse response"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Empty response"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Unexpected reply from server"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Response invalid"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV share"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Enter password for %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Please enter proxy password"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Not a WebDAV-enabled share"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV on %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Could not create request"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Target file already exists"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "The file was externally modified"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Backup file creation failed"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Local Network"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Can't monitor file or directory."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Network"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Accounts are unsupported"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Host closed connection"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Cannot open data connection. Maybe your firewall prevents this?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Data connection closed"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Operation failed"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "No space left on server"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operation unsupported"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Permission denied"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Page type unknown"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Invalid filename"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:388
+#: ../daemon/gvfsbackendftp.c:413 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Invalid reply"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "broken transmission"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Could not connect to host"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Enter password for FTP as %s on %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Enter password for FTP on %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Password dialogue cancelled"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "FTP on %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "FTP as %s on %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "File is directory"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "backups not supported yet"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "filename too long"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Invalid destination filename"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Directory or file exists"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: No such file or directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Invalid filename"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Not Supported"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digital Camera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s Camera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s Audio Player"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Camera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Audio Player"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "No device specified"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Cannot create gphoto2 context"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Error creating camera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Error loading device information"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Error looking up device information"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Error getting device information"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Error setting up camera communications port"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Error initialising camera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 mount on %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "No camera specified"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Error creating file object"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Error getting file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Error getting data from file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Malformed icon identifier '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Error seeking in stream on camera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Not a directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Failed to get folder list"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Failed to get file list"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Error creating directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Name already exists"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "New name too long"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Error renaming directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Error renaming file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Directory '%s' is not empty"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Error deleting directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Error deleting file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Can't write to directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Cannot allocate new file to append to"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Cannot read file to append to"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Cannot get data of file to append to"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Error writing file"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Not supported (not same directory)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Not supported (src is dir, dst is dir)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Not supported (src is dir, dst is existing file)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Not supported (src is file, dst is dir)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP Client Error: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (invalid encoding)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Directory notification not supported"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows Network"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Network Location Monitor"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s on %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB support missing. Please contact your software vendor"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Connection to the device lost"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Device requires a software update"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh program unexpectedly exited"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Hostname not known"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "No route to host"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Connection refused by server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Host key verification failed"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Unable to spawn ssh program"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Unable to spawn ssh program: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Timed out when logging in"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Enter passphrase for key"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Enter password"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Can't send password"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Log In Anyway"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Cancel Login"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Login dialogue cancelled"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Can't send host identity confirmation"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protocol error"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "SFTP for %s on %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "SFTP on %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Unable to find supported ssh command"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Failure"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Invalid reply received"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Invalid icon_id '%s' in OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Error creating backup file: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Unable to create temporary file"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Can't move directory over directory"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Password required for share %s on %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Internal Error (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Failed to mount Windows share"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Unsupported seek type"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Backup file creation failed: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Error deleting file: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Error moving file: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Error removing target file: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Can't recursively move directory"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows Shares Filesystem Service"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Password required for %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows shares on %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Failed to retrieve share list from server"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "The file is not a mountable"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Not a regular file"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows Network Filesystem Service"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "The wastebasket may not be deleted"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Items in the wastebasket may not be modified"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Wastebasket"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Invalid backend type"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Error sending fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symlinks not supported by backend"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Invalid dbus message"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Replace old daemon."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Don't start fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Daemon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Main daemon for GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Try \"%s --help\" for more information."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Invalid arguments from spawned child"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount failed: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "The specified location is not mounted"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "The specified location is not supported"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Location is already mounted"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Location is not mountable"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Blank CD-ROM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Blank CD-R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Blank CD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Blank DVD-ROM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Blank DVD-RAM Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Blank DVD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Blank DVD+R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Blank DVD+RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Blank DVD+R DL Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Blank Blu-Ray Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Blank Blu-Ray R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Blank Blu-Ray RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Blank HD DVD Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Blank HD DVD-R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Blank HD DVD-RW Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Blank MO Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Blank Disc"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s Drive"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s Drive"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Floppy Drive"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Software RAID Drive"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB Drive"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA Drive"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI Drive"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire Drive"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tape Drive"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash Drive"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick Drive"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia Drive"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC Drive"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip Drive"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz Drive"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb Drive"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Mass Storage Drive"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Failed to eject media; one or more volumes on the media are busy."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Mixed Audio/Data Disc"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s Media"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s Encrypted Data"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: error opening file: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, error writing to stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: error reading: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:error closing: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - concatenate LOCATIONS to standard output."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: missing locations"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: error opening location: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: error launching application: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - open FILES with registered application."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "File unavailable"
+#~ msgstr "File unavailable"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (in wastebasket)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Can't delete wastebasket"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Wastebasket directory notification not supported"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB Media"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB Media"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB Media"
+
+#~ msgid "File does not exist"
+#~ msgstr "File does not exist"
diff --git a/trunk/po/es.po b/trunk/po/es.po
new file mode 100644
index 00000000..dee27ada
--- /dev/null
+++ b/trunk/po/es.po
@@ -0,0 +1,1670 @@
+# translation of gvfs.HEAD.po to Español
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Jorge González <jorgegonz@svn.gnome.org>, 200, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
+"product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-04 19:03+0000\n"
+"PO-Revision-Date: 2009-02-04 20:27+0100\n"
+"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
+"Language-Team: Español <gnome-es-list@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"La operación no está soportada, los archivos están en diferentes puntos de "
+"montaje"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info devolvió un valor no válido"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info devolvió un valor no válido"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "No se pudo obtener el descriptor del archivo de flujo"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open devolvió un valor no válido"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "No se obtuvo un descriptor del archivo de flujo"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call devolvió un valor no válido"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info devolvió un valor no válido"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "No se pudo encontrar el punto de montaje adjunto"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nombre de archivo no válido %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info devolvió un valor no válido"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "El valor devuelto por monitor_dir no es válido"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "El valor devuelto por monitor_file no es válido"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Se canceló la operación"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Error en el protocolo de flujo: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Final de flujo"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "No se permite buscar en el flujo"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "La operación de consulta de información no está soportada"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "No se soporta consulta de información en flujo"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Error al obtener la información de montaje: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Error al conectar con el demonio: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read devolvió un valor no válido"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Error al crear el socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Error al conectar con el socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Formato de información del archivo no válido"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "El contenido de la lista de información del atributo no es válido"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Error al inicializar Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Error al crear el resolutor Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Error al resolver «%s» servicio «%s» en el dominio «%s»"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Error al resolver «%s» servicio «%s» en el dominio «%s». Faltan uno o más "
+"registros TXT. Claves requeridas: «%s»."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Expiró el tiempo al resolver «%s» servicio «%s» en el dominio «%s»"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd triplemente codificado «%s» mal formado"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "No se puede manejar la versión %d de la codificación GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Datos de entrada GVfsIcon malformados"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Error al conectar con D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Sistema de archivos %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Error: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Uso: %s --spawner dbus-id ruta_del_objeto"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Uso: %s clave=valor clave=valor …"
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "No se especificó el tipo de montaje"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "el punto de montaje para %s ya se está usando"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "error al iniciar el demonio de montado"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ en %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "No se especificó un nombre de servidor"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Especificación de montaje no válida"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:399
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:647
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "El archivo no existe"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:446
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:694
+msgid "The file is not a directory"
+msgstr "El archivo no es un directorio"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Grabar"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "No se pudo crear el directorio temporal"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "El archivo o directorio no existe"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "El directorio no está vacío"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "No se puede copiar un archivo sobre un directorio"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Creador de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "El archivo ya existe"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "El backend no soporta la operación"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "El archivo o directorio no existe en la ruta de destino"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "No se puede copiar un directorio sobre otro directorio"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "El archivo destino ya existe"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "No se puede copiar recursivamente un directorio"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "No soportado"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "No se pudo conectar con el bus del sistema"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "No se pudo crear el contexto libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "No se puede inicializar libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "No se especificó una unidad"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "No se pudo encontrar la unidad %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "La unidad %s no contiene archivos de sonido"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "CDDA montado en %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disco de sonido"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "El sistema de archivos está ocupado: %d archivo abierto"
+msgstr[1] "El sistema de archivos está ocupado: %d archivos abiertos"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "El archivo %s no existe en la unidad %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Error de «paranoia» en la unidad %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Error al buscar en el flujo en la unidad %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "No existe el archivo"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "El archivo no existe o no es una pista de sonido"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Servicio de sistema de archivos de Audio CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Equipo"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistema de archivos"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "No se puede abrir el directorio"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "No se puede abrir el archivo montable"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Error interno: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "No se puede montar el archivo"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "No hay un soporte en la unidad"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "No es un archivo montable"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "No se puede desmontar el archivo"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "No se puede expulsar el archivo"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Error HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "No se pudo analizar la respuesta"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Respuesta vacía"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Respuesta inesperada del servidor"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Respuesta no válida"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Compartición WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Introduzca la contraseña para %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Introduzca la contraseña del proxy"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "No es una compartición activada WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV en %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "No se pudo crear la petición"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "El archivo destino ya existe"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "El archivo se modificó externamente"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Falló la creación del archivo de respaldo"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:493 ../daemon/gvfsbackendnetwork.c:394
+msgid "Local Network"
+msgstr "Red local"
+
+#: ../daemon/gvfsbackenddnssd.c:737 ../daemon/gvfsbackendnetwork.c:798
+msgid "Can't monitor file or directory."
+msgstr "No se puede monitorizar el archivo o directorio."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:755
+msgid "Dns-SD"
+msgstr "DNS-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:756 ../daemon/gvfsbackendnetwork.c:733
+#: ../daemon/gvfsbackendnetwork.c:883 ../daemon/gvfsbackendnetwork.c:884
+msgid "Network"
+msgstr "Red"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Las cuentas no están soportadas"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "El servidor cerró la conexión"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"No se puede abrir la conexión de datos. ¿Quizá su cortafuegos lo esté "
+"impidiendo?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Se cerró la conexión de datos"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Falló la operación"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "No queda espacio libre en el servidor"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "La operación no está soportada"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Permiso denegado"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Tipo de página desconocido"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nombre de archivo no válido"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Se recibió una respuesta no válida"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmisión rota"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "No se pudo conectar con el equipo"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Introduzca la contraseña para el ftp %s en %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Introduzca la contraseña para el ftp en %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Se canceló el diálogo de la contraseña"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp en %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s en el ftp de %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "El archivo es un directorio"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "aún no se soportan los respaldos"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "el nombre de archivo es demasiado largo"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nombre de archivo de destino no válido"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: El directorio o archivo ya existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: El archivo o directorio no existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Nombre de archivo no válido"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: No soportado"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Cámara digital (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Cámara %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Reproductor de sonido %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Reproductor de sonido"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "No se especificó el dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "No se puede crear el contexto gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Error al crear la cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Error al cargar la información del dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Error al buscar la información del dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Error al obtener la información del dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Error al establecer el puerto de comunicaciones de la cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Error al inicializar la cámara"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 montado en %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "No se especificó ninguna cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Error al crear el archivo objeto"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Error al obtener el archivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Error al obtener datos del archivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificador de icono «%s» mal formado"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Error al buscar en el flujo en la cámara %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "No es un directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Falló al obtener la lista de carpetas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Falló al obtener la lista de archivos"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Error al crear el directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "El nombre ya existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "El nuevo nombre es demasiado largo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Error al renombrar el directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Error al renombrar el archivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "El directorio «%s» no está vacío"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Error al borrar el directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Error al borrar el archivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "No se puede escribir en el directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "No se puede asignar el nuevo archivo en el que añadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "No se puede leer el archivo en el que añadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "No se puede obtener los datos del archivo en el que añadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Error al escribir el archivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "No soportado (no es el mismo directorio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "No soportado (src es un directorio, dst es un directorio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "No soportado (src es un directorio, dst es un archivo existente)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "No soportado (src es un archivo, dst es un directorio)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Error HTTP en el cliente: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codificación no válida)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "No se soporta la notificación de directorios"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Red de Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:932
+msgid "Network Location Monitor"
+msgstr "Monitor de ubicación de red"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s en %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Falta el soporte para USB. Contacte con el fabricante de su software."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Se perdió la conexión con el dispositivo"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "El dispositivo requiere una actualización de software"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "el programa de ssh finalizó inesperadamente"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "El nombre de servidor desconocido"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "No hay una ruta al servidor"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "El servidor rechazó la conexión"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Falló la verificación de la clave del servidor"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "No se pudo lanzar el programa ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "No se pudo lanzar el programa ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Expiró el tiempo para iniciar la sesión"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Introduzca una frase de paso para la clave"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Introduzca la contraseña"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "No se puede enviar la contraseña"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Iniciar sesión de todas formas"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Cancelar inicio de sesión"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Se desconoce la identidad del equipo remoto (%s).\n"
+"Esto sucede cuando inicia sesión por primera vez en un equipo.\n"
+"\n"
+"La identidad enviada por el equipo remoto es %s. Contacte con el "
+"administrador del sistema si quiere estar completamente seguro de que es "
+"seguro continuar."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Se canceló el inicio de sesión"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "No se puede enviar la confirmación de identidad del equipo"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Error de protocolo"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp para %s en %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp en %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "No se pudo encontrar el comando ssh soportado"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Fallo"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Se recibió una respuesta no válida"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Identificador de icono «%s» no válido en OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Error al crear el archivo de respaldo: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "No se pudo crear el archivo temporal"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "No se puede mover un directorio sobre un directorio"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Se requiere contraseña para la compartición %s en %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Error interno (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Falló al montar la compartición Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Tipo de búsqueda no soportado"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Falló la creación del archivo de respaldo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Error al borrar el archivo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Error al mover el archivo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Error al eliminar el archivo destino: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "No se puede mover recursivamente un directorio"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Servicio del sistema de archivos compartidos de Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Se requiere contraseña para %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Comparticiones Windows en %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Falló al obtener la lista de compartición del servidor"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "El archivo no se puede montar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "No es un archivo regular"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Servicio del sistema de archivos de red de Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+#| msgid "Items in the trash may not be modified"
+msgid "The trash folder may not be deleted"
+msgstr "No se puede borrar la carpeta de la papelera"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Los elementos en la papelera no se deben modificar"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Papelera"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipo de backend no válido"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Error al enviar el descriptor de archivo: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "El backend no soporta enlaces simbólicos"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Mensaje de D-Bus no válido"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Reemplace el demonio antiguo."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "No iniciar fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Demonio GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Demonio principal para GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Intente \"%s --help\" para obtener más información."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Argumentos no válidos para el hijo lanzado"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Falló automount: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "La ubicación especificada no está montada"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "La ubicación especificada no está soportada"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "La ubicación ya está montada"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "La ubicación no es montable"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disco CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disco CD-ROM virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disco CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disco CD-R virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disco CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disco CD-RW virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disco DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disco DVD-ROM virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disco DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disco DVD-RAM virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disco DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disco DVD-RW virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disco DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disco DVD+R virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disco DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disco DVD+RW virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disco DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disco DVD+R DL virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disco Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disco Blu-Ray virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disco HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disco DVD HD virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disco HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disco HD DVD-R virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disco DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disco HD DVD-RW virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disco MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disco MO virgen"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disco"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disco virgen"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unidad %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unidad %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disquete"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unidad RAID por software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unidad USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Unidad ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Unidad SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unidad FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unidad de cinta"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unidad CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unidad MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unidad SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unidad SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unidad Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unidad Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Unidad Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unidad de almacenamiento masivo"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Falló al expulsar el medio, uno o más volúmenes están ocupados en el medio."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f KiB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MiB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GiB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disco de sonido y datos"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Soporte %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Datos cifrados %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: error al abrir el archivo: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, error al escribir en stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: error al leer: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:error al cerrar: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "UBICACIÓN… - concatenar las UBICACIONES con una salida estándar."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenar archivos en ubicaciones e imprimirlos en la salida estándar. "
+"Funciona igual que la utilidad tradicional «cat», pero usando la ubicación "
+"gvfs en lugar de los archivos locales: por ejemplo, puede usar algo como "
+"smb://servidor/recurso/archivo.txt como una ubicación para concatenar."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: use una tibería a traes de «cat» si necesita las opciones de formateo "
+"tales como -n, -T u otras."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: faltan ubicaciones"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: error al abrir la ubicación: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: error al lanzar la aplicación: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ARCHIVOS… - abre ARCHIVOS con la aplicación registrada."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Abre el/los archivo/s con la aplicación predeterminada registrada para "
+"manejar el tipo de archivo."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "No se puede borrar la papelera"
+
+#~ msgid "Can't pull trash"
+#~ msgstr "No se puede vaciar la papelera"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (en la papelera)"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "No se soporta la notificación de la papelera"
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr "Error al listar las carpetas para averiguar el prefijo de ignorado"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "Error al crear la lista del puerto de información"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr ""
+#~ "Error al obtener el puerto de información desde la lista del puerto de "
+#~ "información"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "El sistema de archivos está ocupado: %d archivos abiertos"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Error al listar las carpetas"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "Error al listar los archivos en la carpeta"
diff --git a/trunk/po/et.po b/trunk/po/et.po
new file mode 100644
index 00000000..9d2749ba
--- /dev/null
+++ b/trunk/po/et.po
@@ -0,0 +1,1556 @@
+# GVFS'i eesti keele tõlge.
+# Estonian translation of GVFS.
+#
+# Copyright (C) 2008 The GNOME Project.
+# This file is distributed under the same license as the gvfs package.
+#
+# Ivar Smolin <okul@linue.ee>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-21 15:25+0000\n"
+"PO-Revision-Date: 2008-08-23 14:16+0300\n"
+"Last-Translator: Ivar Smolin <okul@linux.ee>\n"
+"Language-Team: Estonian <gnome-et@linux.ee>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr "Operatsioon pole toetatud, failid asuvad eri ketastel"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "Voo failideskriptorit pole võimalik hankida"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr "open tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr "Ei õnnestunud voofaili deskriptiorit saada"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info tagastas vigase väärtuse"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Vigane failinimi %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir tagastas vigase väärtuse"
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file tagastas vigase väärtuse"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Viga vooprotokollis: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Voo lõpp"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operatsioon katkestati"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Andmevoogude korral pole asukohale hüppamine toetatud"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Andmete pärimise operatsioon pole toetatud"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Andmevoogude korral pole andmepäring toetatud"
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Viga ühendamise andmete hankimisel: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Viga deemoniga ühendumisel: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Viga sokli loomisel: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Viga sokliga ühendumisel: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Vigane failiandmete vorming"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Viga D-Bus'iga ühendumisel: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s failisüsteemi teenus"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Viga: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Kasutamine: %s --spawner dbus-id objekti_rada"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Kasutamine: %s võti=väärtust võti=väärtust ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ühendamise liiki pole määratud"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "ühenduspunkt %s on juba töös"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "viga ühendamisdeemoni käivitamisel"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "hosti %s /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Hostinimi on määramata"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1449 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr "Vigane ühendamiskirjeldus"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "Faili pole olemas"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "Fail pole kataloog"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Ajutist kataloogi pole võimalik luua"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "No such file or directory"
+msgstr "Sellist faili või kataloogi ei ole"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2036
+msgid "Directory not empty"
+msgstr "Kataloog pole tühi"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-looja"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2763
+msgid "File exists"
+msgstr "Fail on olemas"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr "Sihtkohas pole sellist faili ega kataloogi"
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Target file exists"
+msgstr "Sihtfail on juba olemas"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr "Kataloogi pole võimalik rekursiivselt kopeerida"
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2348
+#: ../daemon/gvfsbackendgphoto2.c:2556 ../daemon/gvfsbackendgphoto2.c:2651
+#: ../daemon/gvfsbackendgphoto2.c:2742
+msgid "Not supported"
+msgstr "Pole toetatud"
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot connect to the system bus"
+msgstr "Süsteemse siiniga pole võimalik ühendust võtta"
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot create libhal context"
+msgstr "libhal-konteksti pole võimalik luua"
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1427
+msgid "Cannot initialize libhal"
+msgstr "libhal-i pole võimalik lähtestada"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr "Ketas on määramata"
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Seadet %s pole võimalik leida"
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Seade %s ei sisalda audiofaile"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda ühendus seadmes %s"
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Audioplaat"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1655
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Failisüsteem on hõivatud: %d fail on avatud"
+msgstr[1] "Failisüsteem on hõivatud: %d faili on avatud"
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Faili %s pole %s kettal"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "'paranoia' teegi viga seadmega %s"
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1711
+#, c-format
+msgid "No such file"
+msgstr "Sellist faili ei ole"
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Faili pole olemas või pole see audiofail"
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr "Audio-CD failisüsteemi teenus"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Arvuti"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Failisüsteem"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1703
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+msgid "Can't open directory"
+msgstr "Kataloogi pole võimalik avada"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "Ühendatavat faili pole võimalik avada"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Sisemine viga: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "Faili pole võimalik ühendada"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "Seadmes puudub meedium"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Pole ühendatav fail"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "Faili pole võimalik lahti ühendada"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "Faili pole võimalik väljastada"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1516
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP viga: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "Vastust pole võimalik analüüsida"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Tühi vastus"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Ootamatu vastus serverilt"
+
+#: ../daemon/gvfsbackenddav.c:1149 ../daemon/gvfsbackenddav.c:1651
+msgid "Response invalid"
+msgstr "Vastus on vigane"
+
+#: ../daemon/gvfsbackenddav.c:1292
+msgid "WebDAV share"
+msgstr "WebDAV'i jagatud kataloog"
+
+#: ../daemon/gvfsbackenddav.c:1294
+#, c-format
+msgid "Enter password for %s"
+msgstr "Sisesta %s parool"
+
+#: ../daemon/gvfsbackenddav.c:1297
+msgid "Please enter proxy password"
+msgstr "Palun sisesta proksi parool"
+
+#: ../daemon/gvfsbackenddav.c:1520 ../daemon/gvfsbackenddav.c:1524
+msgid "Not a WebDAV enabled share"
+msgstr "Pole WebDAV'i jagatud kataloog"
+
+#: ../daemon/gvfsbackenddav.c:1547
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV hostil %s"
+
+#: ../daemon/gvfsbackenddav.c:1607 ../daemon/gvfsbackenddav.c:1680
+msgid "Could not create request"
+msgstr "Päringut pole võimalik luua"
+
+#: ../daemon/gvfsbackenddav.c:1743 ../daemon/gvfsbackenddav.c:1996
+#: ../daemon/gvfsbackenddav.c:2107 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr "Sihtfail on juba olemas"
+
+#: ../daemon/gvfsbackenddav.c:1816 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr "Faili on mõne teise programmi poolt muudetud"
+
+#: ../daemon/gvfsbackenddav.c:1847 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr "Tõrge varufaili loomisel"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Faili või kataloogi pole võimalik monitoorida."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Võrk"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "Kontod pole toetatud"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "Host sulges ühenduse"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Andmeühendust pole võimalik avada. Võibolla tulemüür takistab seda?"
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "Andmeühendus on suletud"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Operatsioon nurjus"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "Serveris pole vaba ruumi"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Operatsioon pole toetatud"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Ligipääs keelatud"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Vigane failinimi"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Vigane vastus"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "vigane ülekanne"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "Hostiga pole võimalik ühendust võtta"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Sisesta hosti %s ftp-parool"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Paroolidialoog tühistati"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp hostil %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp kasutajanimega %s hostil %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "Fail on kataloog"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "varukoopiad pole veel toetatud"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "failinimi on liiga pikk"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "Vigane sihtfaili nimi"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Kataloog või fail on juba olemas"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Sellist faili või kataloogi ei ole"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Vigane failinimi"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Pole toetatud"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digikaamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s kaamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s audioesitaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kaamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Audioesitaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get folder list"
+msgstr "Kataloogide nimekirja pole võimalik hankida"
+
+#: ../daemon/gvfsbackendgphoto2.c:1442
+msgid "No device specified"
+msgstr "Seade on määramata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1459
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 konteksti pole võimalik luua"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469
+msgid "Error creating camera"
+msgstr "Viga kaamera loomisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1482 ../daemon/gvfsbackendgphoto2.c:1492
+msgid "Error loading device information"
+msgstr "Viga seadme andmete laadimisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1504
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error getting device information"
+msgstr "Viga seadme andmete hankimisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1527
+msgid "Error setting up camera communications port"
+msgstr "Viga kaamera suhtluspordi andmete seadmisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1538
+msgid "Error initializing camera"
+msgstr "Viga kaamera lähtestamisel"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1552
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 ühendatud ketas %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1627
+msgid "No camera specified"
+msgstr "Kaamera on määramata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error creating file object"
+msgstr "Viga failiobjekti loomisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1733
+msgid "Error getting file"
+msgstr "Viga faili hankimisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:1742
+msgid "Error getting data from file"
+msgstr "Viga andmete hankimisel failist"
+
+#: ../daemon/gvfsbackendgphoto2.c:1836 ../daemon/gvfsbackendgphoto2.c:3010
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1975 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Pole kataloog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2071
+msgid "Failed to get file list"
+msgstr "Failide nimekirja pole võimalik hankida"
+
+#: ../daemon/gvfsbackendgphoto2.c:2360
+msgid "Error creating directory"
+msgstr "Viga kataloogi loomisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:2568
+msgid "Name already exists"
+msgstr "Nimi on juba olemas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2579 ../daemon/gvfsbackendgphoto2.c:3200
+msgid "New name too long"
+msgstr "Uus nimi on liiga pikk"
+
+#: ../daemon/gvfsbackendgphoto2.c:2589 ../daemon/gvfsbackendgphoto2.c:3211
+msgid "Error renaming dir"
+msgstr "Viga kataloogi ümbernimetamisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:2601 ../daemon/gvfsbackendgphoto2.c:3223
+msgid "Error renaming file"
+msgstr "Viga faili ümbernimetamisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:2664
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Kataloog '%s' pole tühi"
+
+#: ../daemon/gvfsbackendgphoto2.c:2675
+msgid "Error deleting directory"
+msgstr "Viga kataloogi kustutamisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "Error deleting file"
+msgstr "Viga faili kustutamisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:2752
+msgid "Can't write to directory"
+msgstr "Kataloogi pole võimalik kirjutada"
+
+#: ../daemon/gvfsbackendgphoto2.c:2799
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2813
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2823
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Error writing file"
+msgstr "Viga faili kirjutamisel"
+
+#: ../daemon/gvfsbackendgphoto2.c:3156
+msgid "Not supported (not same directory)"
+msgstr "Pole toetatud (pole sama kataloog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3168
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Pole toetatud (lähtekoht on kataloog, sihtkoht on ka kataloog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3176
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Pole toetatud (lähtekoht on kataloog, sihtkoht on olemasolev fail)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Pole toetatud (lähtekoht on fail, sihtkoht on kataloog)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-kliendi viga: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (vigane kodeering)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Kataloogiteavitus pole toetatud"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windowsi võrk"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Kohalik võrk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Võrguasukoha monitoorija"
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "Kataloog %s serverist %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "Ühendus seadmega on katkenud"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "Seadmele on vaja teha tarkvarauuendus"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "ssh-programm lõpetas ootamatult"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Hostinimi on tundmatu"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Hostini puudub töötav marsruut"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "Server lükkas ühenduse tagasi"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Tõrge hostivõtme verifitseerimisel"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "ssh-programmi pole võimalik käivitada"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh-programmi pole võimalik käivitada: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Sisselogimine ületas ajapiirangu"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Sisesta võtme parool"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Sisesta parool"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "Parooli pole võimalik saata"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Logi ikkagi sisse"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Katkesta sisselogimine"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Kaugarvuti (%s) identiteet on tundmatu.\n"
+"See olukord tekib tavaliselt arvutisse esimese sisselogimise korral.\n"
+"\n"
+"Kaugarvuti poolt saadetud identiteet on %s. Kui sa tahad turvakaalutlustel "
+"selles täiesti kindel olla, siis võta palun ühendust oma süsteemihalduriga."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Sisselogimisdialoog tühistati"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "Hosti identimisandmeid pole võimalik saata"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Protokolli viga"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp hostil %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "Toetatud ssh-käsku pole võimalik leida"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Tõrge"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "Võeti vastu vigane vastus"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Viga varufaili loomisel: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "Ajutist faili pole võimalik luua"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Serveris %2$s asuva jagatud kataloogile %1$s on vaja parooli"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Sisemine viga (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr "Tõrge Windowsi jagatud kataloogi ühendamisel"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Tõrge varufaili loomisel: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Viga faili kustutamisel: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Viga faili ümbertõstmisel: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Viga sihtfaili eemaldamisel: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr "Kataloogi pole võimalik rekursiivselt ümber tõsta"
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr "Windowsi jagatud failisüsteemi teenus"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windowsi jagatud kataloogid serveris %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "Fail pole ühendatav"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Pole tavaline fail"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Windowsi võrgufailisüsteemi teenus"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Prügikast"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (prügikastis)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "Prügikasti pole võimalik kustutada"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Prügikataloogi teavitus pole toetatud"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Vigane taustaprogrammi liik"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Viga fd saatmisel: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operatsioon pole taustaprogrammi poolt toetatud"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Nimeviidad pole taustaprogrammi poolt toetatud"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "Vigane dbus-sõnum"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Vana deemoni asendamine."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Fuse't ei käivitata."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-deemon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS-i peadeemon"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Täiendava teabe jaoks proovi \"%s --help\"."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Tõrge automaatühendamisel: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "Määratud asukoht pole ühendatud"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "Määratud asukoht pole toetatud"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "Asukoht on juba ühendatud"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "Asukoht pole ühendatav"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-ajam"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-ajam"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Flopiajam"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Tarkvaraline RAID-salvesti"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-ajam"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-ajam"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-ajam"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire-ajam"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Magnetlintsalvesti"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-ajam"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-ajam"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-ajam"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-ajam"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-ajam"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-ajam"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Mälupulk"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Massalvesti"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Tõrge meediumi väljastamisel, üks või enam meediumit on hõivatud."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+msgid "Mixed Audio/Data Disc"
+msgstr "Audio ja andmete segaplaat"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, c-format
+msgid "%s Media"
+msgstr "%s meedium"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s krüptitud andmed"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM plaat"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tühi CD-ROM plaat"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R plaat"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tühi CD-R plaat"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tühi CD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM plaat"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tühi DVD-ROM plaat"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM plaat"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tühi DVD-RAM plaat"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tühi DVD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R plaat"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tühi DVD+R plaat"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW plaat"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tühi DVD+RW plaat"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL plaat"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tühi DVD+R DL plaat"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray plaat"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tühi Blu-Ray plaat"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R plaat"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tühi Blu-Ray R plaat"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW plaat"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tühi Blu-Ray RW plaat"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD plaat"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tühi HD DVD plaat"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R plaat"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tühi HD DVD-R plaat"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tühi HD DVD-RW plaat"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO plaat"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tühi MO plaat"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Plaat"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tühi plaat"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: viga faili avamisel: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, viga standardväljundisse kirjutamisel"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: viga lugemisel: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: viga sulgemisel: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "ASUKOHT... - ASUKOHTADE ühteliitmine standardväljundisse."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Asukohtades asuvate failide ühteliitmine ning standardväljundisse "
+"väljastamine. Töötab nagu klassikaline utiliit cat, kuid kasutab kohalike "
+"failide asemel gvfs-i asukohti. Näiteks võib failide liitmiseks kasutada "
+"asukohta smb://server/resource/file.txt."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Märkus: vormindusvõtmete (näiteks -n, -T või mõne muu) kasutamiseks suuna "
+"väljund programmile cat."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: asukohad on puudu"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: viga asukoha avamisel: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: viga rakenduse käivitamisel: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FAILID... - FAILIDE avamine registreeritud rakenduse abil."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Faili(de) avamine selle failitüübi käsitlemiseks registreeritud vaikimisi "
+"rakendusega."
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "Viga pordi andmete hankimisel pordi andmete nimekirjast"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "Failisüsteem on hõivatud: %d faili on avatud"
+
+#~ msgid "File unavailable"
+#~ msgstr "Fail pole saadaval"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB meedium"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB meedium"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB meedium"
diff --git a/trunk/po/eu.po b/trunk/po/eu.po
new file mode 100644
index 00000000..af436eed
--- /dev/null
+++ b/trunk/po/eu.po
@@ -0,0 +1,1629 @@
+# translation of eu.po to Basque
+# translation of gvfs.HEAD.po to Basque
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>, 2008, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: eu\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-12 20:29+0100\n"
+"PO-Revision-Date: 2009-02-12 20:37+0100\n"
+"Last-Translator: Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>\n"
+"Language-Team: Basque <itzulpena@euskalgnu.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Eragiketa ez dago onartuta, fitxategiak muntai desberdinetan"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "'get_info'-k balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "'query_info'-k balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Ezin izan da korronte-fitxategiaren deskriptorea lortu"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "'open'-ek balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Ez da korronte-fitxategiaren deskriptorea lortu"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "'call'-ek balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "'get_filesystem_info'-k balio baliogabea itzuli du"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Ezin izan da muntai inguratua aurkitu"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "%s fitxategi-izen baliogabea"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "'query_filesystem_info'-k balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "'monitor_dir'-ek balio baliogabea itzuli du"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "'monitor_file'-k balio baliogabea itzuli du"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Eragiketa bertan behera utzi da"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Errorea korrontearen protokoloan: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Korrontearen amaiera"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Ez da bilaketarik onartzen korrontean"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Informazioa kontsultatzeko eragiketa ez dago onartuta"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Ez da kontsultaren informaziorik onartzen korrontean"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Errorea muntaiaren informazioa lortzean: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Errorea daemonarekin konektatzean: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "'open_icon_for_read'-ek balio baliogabea itzuli du"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Errorea socket-a sortzean: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Errorea socket-arekin konektatzean: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Fitxategiaren informazioaren formatu baliogabea"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Atributuaren informazio-zerrendaren eduki baliogabea"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Errorea Avahi hasieratzean: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Errorea Avahi ebazlea sortzean: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Errorea \"%s\" zerbitzuko \"%s\" ebaztean\"%s\" domeinuan"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Errorea \"%s\" zerbitzuko \"%s\" ebaztean\"%s\" domeinuan. "
+"TXT erregistro bat edo gehiago falta da. Behar diren gakoak: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Denbora iraungitua \"%s\" zerbitzuko \"%s\" ebaztean\"%s\" domeinuan"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Gaizki osatutako '%s' dns-sd kodeketa_hirukoitza"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Ezin da GVfsIcon kodeketaren %d bertsioa kudeatu"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Gaizki osatutako GVfsIcon-en sarrerako datuak"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Errorea 'D-Bus'ekin konektatzean: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s fitxategi-sistemaren zerbitzua"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Errorea: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Erabilera: %s --spawner dbus-id objektu-bidea"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Erabilera: %s gakoa=balioa gakoa=balioa ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ez da muntai motarik zehaztu"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s(r)en muntatze-puntua jadanik exekutatzen ari da"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "Errorea muntatze-daemona abiaraztean"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s(e)ko /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Ez da ostalari-izenik zehaztu"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Muntaiaren zehaztapen baliogabea"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Fitxategia ez da existitzen"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Fitxategia ez da direktorioa"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Grabatu"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Ezin da aldi baterako direktorioa sortu"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Ez dago halako fitxategi edo direktoriorik"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Direktorioa ez dago hutsik"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Ezin da fixtategia direktorio gainean kopiatu"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD sortzailea"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Fitxategia badago lehendik ere"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Motorrak ez du eragiketa onartzen"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Ez dago halako fitxategi edo direktoriorik helburuko bide-izenean"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Ezin da direktorioa direktorio gainean kopiatu"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Helburuko fitxategia badago lehendik ere"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Ezin da direktorioa errekurtsiboki kopiatu"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Ez dago onartuta"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Ezin izan da sistemako busarekin konektatu"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Ezin da libhal testuingurua sortu"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Ezin da libhal hasieratu"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Ez da unitaterik zehaztu"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Ezin da %s unitatea aurkitu"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "%s unitateak ez dauka audio-fitxategirik"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda hemen muntatuta: %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio-diskoa"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Fitxategi-sistema lanpetuta dago: fitxategi %d irekita"
+msgstr[1] "Fitxategi-sistema lanpetuta dago: %d fitxategi irekita"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Ez dago %s fitxategia %s unitatean"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "'Paranoia' programaren errorea %s unitatean"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Errorea korrontean bilaketa egitean %s unitatean"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Ez dago halako fitxategirik"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Fitxategia ez da existitzen edo ez da audioko pista bat"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Audio CDaren fitxategi-sistemaren zerbitzua"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Ordenagailua"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Fitxategi-sistema"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Ezin da direktorioa ireki"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Ezin da fitxategi muntagarria ireki"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Barneko errorea: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Ezin da fitxategia muntatu"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Ez dago euskarririk unitatean"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ez da fitxategi muntagarria"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Ezin da fitxategia desmuntatu"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Ezin da fitxategia egotzi"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP errorea: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Ezin izan da erantzuna analizatu"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Erantzun hutsa"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Ustekabeko erantzuna zerbitzaritik"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Erantzun baliogabea"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV partekatzea"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Sartu %s(r)en pasahitza"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Sartu proxyaren pasahitza"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Ez da gaitutako WebDAV partekatzea"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV %s(e)n"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Ezin izan da eskaera sortu"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Helburuko fitxategia badago lehendik ere"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Fitxategia kanpotik aldatu da"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Huts egin du babeskopiaren fitxategia sortzean"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Sare lokala"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Ezin da fitxategia edo direktorioa monitorizatu."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "DNS-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Sarea"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Kontuak ez daude onartuta"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Ostalariak konexioa itxi du"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Ezin da datuen konexioa ireki. Agian suebakiak eragozten du?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Datuen konexioa itxita"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Eragiketak huts egin du"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Ez dago leku librerik zerbitzarian"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Eragiketa ez dago onartuta"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Baimena ukatuta"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Orrialde mota ezezaguna"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Fitxategi-izen baliogabea"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Erantzun baliogabea"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmisioa hautsita"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Ezin izan da ostalariarekin konektatu"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Sartu pasahitza %s gisa %s ftp-an"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Sartu %s(r)en Ftp-aren pasahitza"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Pasahitzaren elkarrizketa-koadroa bertan behera utzita"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s(r)en ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp %s gisa %s(r)en"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Fitxategia direktorioa da"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "babeskopiak ez daude onartuta oraindik"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "fitxategi-izena luzeegia"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Helburuko fitxategi-izen baliogabea"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: direktorioa edo fitxategia badago lehendik ere"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: ez dago halako fitxategi edo direktoriorik"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: fitxategi-izen baliogabea"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ez dago onartuta"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Kamera digitala (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s audio-erreproduzigailua"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Audio-erreproduzigailua"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Ez da gailurik zehaztu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Ezin da gphoto2 testuingurua sortu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Errorea kamera sortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Errorea gailuaren informazioa kargatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Errorea gailuaren informazioa bilatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Errorea gailuaren informazioa lortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Errorea kameraren komunikazio-ataka ezartzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Errorea kamera hasieratzean"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 hemen muntatuta: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Ez da kamerarik zehaztu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Errorea fitxategi-objektua sortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Errorea fitxategia lortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Errorea fitxategitik datuak lortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Gaizki osatutako '%s' ikono-identifikatzailea"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Errorea %s kamerako korrontean bilaketa egitean"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ez da direktorioa"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Huts egin du karpeten zerrenda lortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Huts egin du fitxategien zerrenda lortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Errorea direktorioa sortzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Izen hori badago lehendik ere"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Izen barria luzeegia da"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Errorea direktorioa izenez aldatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Errorea fitxategia izenez aldatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "'%s' direktorioa ez dago hutsik"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Errorea direktorioa ezabatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Errorea fitxategia ezabatzean"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Ezin da direktorioan idatzi"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Ezin da fitxategi berria esleitu eransteko"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Ezin da fitxategia irakurri eransteko"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Ezin da daturik lortu fitxategitik eransteko"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Errorea fitxategia idaztean"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Ez dago onartuta (ez da direktorio berdina)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Ez dago onartuta (iturb. dir da, helb. dir da)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Ez dago onartuta (iturb. dir da, helb. badagoen fitxategia da)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Ez dago onartuta (iturb. fitxategia da, helb. dir da)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP bezeroaren errorea: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (kodeketa baliogabea)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Direktorioaren jakinarazpena ez dago onartuta"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows sarea"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Sarea kokatzeko monitorea"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s - %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB euskarria falta da. Jar zaitez software hornitzailearekin harremanetan"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Gailuaren konexioa galduta"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Gailuak softwarea eguneratzea eskatzen du"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "'ssh' programa ustekabean amaitu da"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Ostalari-izena ezezaguna"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ez dago biderik ostalariraino"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Zerbitzariak konexioa ukatu du"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Ostalariaren gakoaren egiaztaketak huts egin du"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Ezin da 'ssh' programa abiarazi"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Ezin da 'ssh' programa abiarazi: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Denboraz kanpo saioa hastean"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Sartu gakoaren pasahitza"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Sartu pasahitza"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Ezin da pasahitza bidali"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Sartu saioan hala ere"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Ez sartu saioan"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Urruneko ordenagailuaren (%s) identitatea ezezaguna da.\n"
+"Ordenagailu batean aurreneko aldiz saioa hastean getatu ohi da.\n"
+"\n"
+"Urruneko ordenagailuak bidalitako identitatea %s da. Jarraitzea segurua ote "
+"den jakiteko, jar zaitez sistemako administratzailearekin harremanetan."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Saio-hasieraren elkarrizketa-koadroa bertan behera utzita"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Ezin da ostalari-identitatearen berrespena bidali"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokoloaren errorea"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp %s gisa %s(r)en"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "%s(r)en sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Ezin da onartutako 'ssh' komandoa aurkitu"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Hutsegitea"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Jasotako erantzun baliogabea"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "'%s' ikono-identifikatzaile baliogabea OpenIconForRead-en"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Errorea babeskopiaren fitxategia sortzean: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Ezin da aldi baterako fitxategia sortu"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Ezin da direktorioa direktorio gainera eraman"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Pasahitza behar da %s partekatzeko %s(e)n"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Barneko errorea (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Huts egin du Windows-en partekatzea muntatzean"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Onartu gabeko bilaketa mota"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Huts egin du babeskopiaren fitxategia sortzean: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Errorea fitxategia ezabatzean: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Errorea fitxategia lekuz aldatzean: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Errorea helburuko fitxategia kentzean: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Ezin da direktorioa errekurtsiboki lekuz aldatu"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows-eko fitxategi partekatuen sistemaren zerbitzua"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Pasahitza behar da %s(e)n"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows-ek partekatua %s(e)n"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Huts egin du partekatutako zerrenda eskuratzean zerrendatik"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Fitxategia ez da muntagarria"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ez da fitxategi erregularra"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows sareko fitxategi-sistemaren zerbitzua"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Zakarrontzia karpeta ezin da ezabatu"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Zakarrontziko elementuak ezin dira eraldatu"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Zakarrontzia"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Motor mota baliogabea"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Errorea fd bidaltzean: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Motorrak ez du esteka sinbolikorik onartzen"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "D-BUSen mezu baliogabea"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Ordeztu daemon zaharra."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Ez hasi fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS daemona"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFSren daemon nagusia"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Saiatu \"%s --help\" komandoarekin informazio gehiagorako."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Abiatutako umearen argumentu baliogabeak"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Huts egin du automatikoki muntatzean: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Zehaztutako kokalekua ez da muntatu"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Zehaztutako kokalekua ez dago onartuta"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Kokalekua jadanik muntatuta dago"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Kokalekua ez da muntagarria"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "CD-RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "CD-R disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "CD-RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "DVD-ROM disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "DVD-RAM disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "DVD-RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "DVD+R disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "DVD+RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "DVD+R DL disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Blu-Ray disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Blu-Ray R disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Blu-Ray RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "HD DVD disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "HD DVD-R disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "HD DVD-RW disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "MO disko garbia"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Diskoa"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disko garbia"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROMa"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-Ra"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RWa"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROMa"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+Ra"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RWa"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-Ra"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RWa"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAMa"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±Ra"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RWa"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVDa"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-Ra"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RWa"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "'Blu-ray'a"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "'Blu-ray-R'a"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "'Blu-ray-RE'a"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s unitatea"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s unitatea"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskete unitatea"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Softwareko RAID unitatea"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB unitatea"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA unitatea"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI unitatea"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire unitatea"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Zinta unitatea"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash unitatea"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick unitatea"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia unitatea"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC unitatea"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "ZIP unitatea"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz unitatea"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb unitatea"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Biltegiratze masiboa unitatea"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Huts egin du euskarria egoztean: euskarriko bolumen bat edo gehiago "
+"lanpetuta dago."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Nahastutako Audio/Datuen diskoa"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s euskarria"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s enkriptatutako datuak"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: errorea fitxategia irekitzean: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, errorea irteera estandarrean (stdout) idaztean"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: errorea irakurtzean: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:errorea ixtean: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "KOKALEKUAK... - kateatu KOKALEKUAK irteera estandarrean"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Kokalekuetako fitxategiak kateatu eta irteera estandarrean erakutsi. 'cat' "
+"tresna bezala funtzionatzen du, baina lokaleko kokalekuak erabili ordez gvfs "
+"kokalekuak erabiliz. Adibidez, honelako zerbait erabil dezakezu: smb://"
+"server/resource/file.txt kateatzeko kokaleku gisa."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "Oharra: kanalizatu 'cat' bidez -n, -T edo bestelako formatua emateko."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: kokalekuak falta dira"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: errorea helbidea irekitzean: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: errorea fitxategia abiaraztean: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FITXATEGIAK... - ireki FITXATEGIAK erregistratutako aplikazioarekin."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Fitxategia(k) irekitzen d(it)u fitxategi mota kudeatzeko erregistratutako "
+"aplikazio lehenetsiarekin."
+
diff --git a/trunk/po/fi.po b/trunk/po/fi.po
new file mode 100644
index 00000000..cc941274
--- /dev/null
+++ b/trunk/po/fi.po
@@ -0,0 +1,1624 @@
+# Finnish messages for gvfs
+# Copyright (C) 2008-2009 Free Software Foundation, Inc.
+# Ilkka Tuohela <hile@iki.fi> 2008-2009.
+# Timo Jyrinki <timo.jyrinki@iki.fi>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-19 10:32+0300\n"
+"PO-Revision-Date: 2009-02-19 10:35+0300\n"
+"Last-Translator: Ilkka Tuohela <hile@iki.fi>\n"
+"Language-Team: Finnish <gnome-fi-laatu@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Toiminto ei ole tuettu, tiedostot eri liitospisteissä"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Virheellinen kutsun get_info paluuarvo"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Virheellinen kutsun query_info paluuarvo"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Virran tiedostokuvaajaa ei saatu"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Virheellinen kutsun open paluuarvo"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Virran tiedostokuvaajaa ei saatu"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Virheellinen kutsun paluuarvo"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Virheellinen kutsun get_filesystem_info paluuarvo"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Yllä olevaa liitospistettä ei voitu selvittää"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Virheellinen tiedostonimi %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Virheellinen kutsun query_filesystem_info paluuarvo"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Virheellinen kutsun monitor_dir paluuarvo"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Virheellinen kutsun monitor_file paluuarvo"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Toiminto peruttiin"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Virhe virtaprotokollassa: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Virta loppui"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Virta ei tue siirtymistä"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Tämä tietokysely ei ole tuettu"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Virta ei tue tietojen kyselyä"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Virhe haettaessa tietoja liitospisteestä: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Virhe yhdistettäessä palvelinprosessiin: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Virheellinen kutsun open_icon_for_read paluuarvo"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Virhe luotaessa pistoketta: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Virhe yhdistettäessä pistokkeeseen: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Virheellinen tiedoston tietojen muoto"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Virheellinen määreiden tietolistan sisältö"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Virhe alustettaessa avahia: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Virhe luotaessa avahi-selvittäjää: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Virhe selvitettäessä \"%s\"-palvelua \"%s\" alueella \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Virhe selvitettäessä \"%s\"-palvelua \"%s\" alueella \"%s\". Yksi tai "
+"useampia TXT-tietueita puuttuu. Vaaditut avaimet: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Aikakatkaisu selvitettäessä \"%s\"-palvelua \"%s\" alueella \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Virheellinen dns-sd encoded_triple \"%s\""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon-koodauken versiota %d ei voi käsitellä"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon-syötedata oli virheellinen"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Virhe D-Bus-yhteydessä: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s-tiedostojärjestelmäpalvelu"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Virhe: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Käyttö: %s --spawner dbus-tunniste kohde_polku"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Käyttö: %s avain=arvo avain=arvo"
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Liitostyyppiä ei annettu"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "liitospiste kohteelle %s on jo käynnissä"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "virhe käynnistettäessä liitospalvelinta"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ palvelimella %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Verkkonimeä ei annettu"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Virheellinen liitosmäärittely"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Tiedostoa ei ole olemassa"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Tiedosto ei ole kansio"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Polta"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Väliaikaistiedostoa ei voitu luoda"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Tiedostoa tai kansiota ei löydy"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Kansio ei ole tyhjä"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Tiedostoa ei voi kopioida kansion päälle"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-luontityökalu"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Tiedosto on jo olemassa"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Taustajärjestelmä ei tue toimintoa"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Kohdepolulla ei ole haluttua kansiota tai hakemistoa"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Kansiota ei voi kopioida kansion päälle"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Kohdetiedosto on jo olemassa"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Kansiota ei voi kopioida rekursiivisesti"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Ei tuettu"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Järjestelmäväylään ei saatu yhteyttä"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Libhal-kontekstia ei voi luoda"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Libhal-kirjastoa ei voi alustaa"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Asemaa ei annettu"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Asemaa %s ei löydy"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Asema %s ei sisällä äänitiedostoja"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda-liitos laitteella %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Äänilevy"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Tiedostojärjestelmä on käytössä: %d avoin tiedosto"
+msgstr[1] "Tiedostojärjestelmä on käytössä: %d avointa tiedostoa"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Tiedostoa %s ei löydy asemasta %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "'Paranoia'-virhe asemasta %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Virhe siirryttäessä virrassa asemassa %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Tiedostoa ei löydy"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Tiedostoa ei ole olemassa tai se ei ole ääniraita"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Ääni-CD:n tiedostojärjestelmäpalvelu"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Tietokone"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Tiedostojärjestelmä"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Kansiota ei voi avata"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Liitettävää tiedostoa ei löydy"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Sisäinen virhe: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Tiedostoa ei voi liittää"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Asemassa ei ole mediaa"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ei liitettävissä oleva tiedosto"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Tiedostoa ei voi irrottaa"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Tiedostoa ei voi poistaa asemasta"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-virhe: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Vastausta ei voitu tulkita"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Tyhjä vastaus"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Odottamaton vastaus palvelimelta"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Virheellinen vastaus"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV-jako"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Anna kohteen %s salasana"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Syötä välipalvelimen salasana"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Jako ei tue WebDAV:ia"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV-jako palvelimella %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Pyyntöä ei voitu luoda"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Kohdetiedosto on jo olemassa"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Tiedostoa muokattiin muualta"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Varmuuskopiotiedoston luonti epäonnistui"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Paikallisverkko"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Tiedostoa tai kansiota ei voi tarkkailla."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "DNS-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Verkko"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Tilejä ei ole tuettu"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Palvelin sulki yhteyden"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Datayhteyttä ei voi avata. Ehkä palomuuri estää FTP-datayhteyden?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Datayhteys on suljettu"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Toiminto epäonnistui"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Palvelimella ei ole tilaa jäljellä"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Toiminto ei tue tuettu"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Lupa evätty"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Sivun tyyppi on tuntematon"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Virheellinen tiedostonimi"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Virheellinen vastaus"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "siirto keskeytyi"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Palvelimeen ei saatu yhteyttä"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Anna käyttäjän %s ftp-palvelimen %s ftp-salasana"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Anna palvelimen %s ftp-salasana"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Salasanakysely keskeytettiin"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp palvelimella %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp käyttäjänä %s palvelimella %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "Tiedosto on kansio"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "varmuuskopioita ei vielä tueta"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "tiedostonimi liian pitkä"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Virheellinen kohteen tiedostonimi"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: kansio tai tiedosto on olemassa"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: tiedostoa tai kansiota ei ole olemassa"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: virheellinen tiedostonimi"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ei tuettu"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitaalikamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s-kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s-musiikkisoitin"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Musiikkisoitin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Laitetta ei määritelty"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Gphoto2-kontekstia ei voi luoda"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Virhe luotaessa kameralaitetta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Virhe ladattaessa tietoja laitteesta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Virhe etsittäessä tietoja laitteesta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Virhe pyydettäessä tietoja laitteesta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Virhe asetettaessa kameran yhteysporttia"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Virhe alustettaessa kameraa"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2-liitos laitteella %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Kameraa ei ole annettu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Virhe luotaessa tiedosto-oliota"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Virhe pyydettäessä tiedostoa"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Virhe pyydettäessä tietoja tiedostosta"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Virheellinen kuvaketunniste \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Virhe siirryttäessä virrassa kamerassa %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ei ole kansio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Kansioluetteloa ei saatu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Tiedostoluetteloa ei saatu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Virhe luotaessa kansiota"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Nimi on jo olemassa"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Uusi nimi on liian pitkä"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Virhe nimettäessä kansiota uudestaan"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Virhe nimettäessä tiedostoa uudestaan"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Kansio \"%s\" ei ole tyhjä"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Virhe poistettaessa kansiota"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Virhe poistettaessa tiedostoa"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Kansioon ei voi kirjoittaa"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Uutta tiedostoa, johon piti lisätä, ei voi varata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Tiedostoa, johon piti lisätä, ei voi lukea"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Sisältöä tiedostosta, johon piti lisätä, ei saatu"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Virhe kirjoitettaessa tiedostoa"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Ei tuettu (ei ole sama kansio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Ei tuettu (lähde on kansio, kohde on kansio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Ei tuettu (lähde on kansio, kohde on olemassaoleva tiedosto)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Ei tuettu (lähde on tiedosto, kohde on kansio)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-asiakkaan virhe: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (virheellinen koodaus)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Kansioiden huomautukset eivät ole tuettu"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows-verkko"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Verkkosijaintien tarkkailija"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s palvelimella %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB-tuki puuttuu. Ota yhteyttä ohjelmiston toimittajaan"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Yhteys laitteeseen hukattiin"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Laite vaatii ohjelmistopäivityksen"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Ohjelma ssh sulkeutui odottamatta"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Verkkonimi tuntematon"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ei reittiä palvelimelle"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Palvelin kieltäytyi yhteydestä"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Palvelimen avaimen vahvistus epäonnistui"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Ohjelmaa ssh ei voi käynnistää"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Ohjelmaa ssh ei voi käynnistää: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Aikakatkaisu kirjauduttaessa"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Syötä avaimen salalause"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Syötä salasana"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Salasanaa ei voitu lähettää"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Kirjaudu joka tapauksessa"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Peru kirjautuminen"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Palvelimen \"%s\" identiteettiä ei voitu vahvistaa.\n"
+"Tämä tapahtuu, kun kirjaudut palvelimelle ensimmäistä kertaa.\n"
+"Palvelimen lähettämää tunniste on %s. jos haluat olla täysin varma, että "
+"yhdistäminen on turvallista, ota yhteyttää palvelimen ylläpitäjään."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Kirjautumisikkuna peruttiin"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Palvelimen tunnistusvahvistusta ei voi lähettää"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokollavirhe"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "ftp käyttäjälle %s palvelimella %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp palvelimella %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Tuettua ssh-komentoa ei löydy"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Virhe"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Saatiin virheellinen vastaus"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Virheellinen icon_id \"%s\" kutsussa OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Virhe luotaessa varmuuskopiotiedostoa: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Virhe luotaessa väliaikaistiedostoa"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Kansiota ei voi siirtää kansion päälle"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Jako %s palvelimella %s vaatii salasanan"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Sisäinen virhe (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows-jakoa ei voitu liittää"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Siirtymistyyppi ei ole tuettu"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Varmuuskopiotiedoston luonti epäonnistui: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Virhe poistettaessa tiedostoa: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Virhe siirrettäessä tiedostoa: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Virhe poistettaessa kohdetiedostoa: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Kansiota ei voi siirtää rekursiivisesti"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows-jakojoen tiedostojärjestelmäpalvelu"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s vaatii salasanan"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Palvelimen %s Windows-jaot"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Luetteloa jaoista ei voitu noutaa palvelimelta"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Tiedosto ei ole liitettävissä"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ei ole tavallinen tiedosto"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows-verkon tiedostojärjestelmäpalvelu"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Roskakorikansiota ei voi poistaa"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Roskakorissa olevia tiedostoja ei voi muokata"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Roskakori"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Virheellinen taustajärjestelmän tyyppi"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Virhe lähettäessä tiedostokuvaajaa: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Taustajärjestelmä ei tue symbolisia linkkejä"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Virheellinen dbus-viesti"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Korvaa vanha palvelinprosessi."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Älä käynnistä FUSE:a."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-palvelinprosessi"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS-pääpalvelin"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Saat lisätietoja komennolla \"%s --help\"."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Käynnistetyltä lapsiprosessilta saatiin virheellisiä argumentteja"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automaattinen liittäminen epäonnistui: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Määritelty sijainti ei ole liitetty"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Määritelty sijainti ei ole tuettu"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Sijainti on jo liitetty"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Sijainti ei ole liitettävissä"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tyhjä CD-ROM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tyhjä CD-R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tyhjä CD-RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tyhjä DVD-ROM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tyhjä DVD-RAM-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tyhjä DVD-RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tyhjä DVD+R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tyhjä DVD+RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tyhjä DVD+R DL-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tyhjä Blu-Ray-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tyhjä Blu-Ray R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tyhjä Blu-Ray RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tyhjä HD DVD-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tyhjä HD DVD-R-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tyhjä HD DVD-RW-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tyhjä MO-levy"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Levy"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tyhjä levy"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-Ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-Ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-Ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-asema"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-asema"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Levykeasema"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Ohjelmistopohjainen RAID-levy"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-asema"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-asema"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-asema"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire-asema"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Nauha-asema"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-asema"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-asema"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-asema"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-asema"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-asema"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-asema"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Muistitikku"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Massatallennusasema"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Asemaa ei voitu avata: yksi tai useampi taltio medialla on käytössä."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kt"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f Mt"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f Gt"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Yhdistetty ääni- ja datalevy"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Media %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Salattua tietoa %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: virhe avattaessa tiedostoa: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, virhe kirjoitettaessa oletustulosteeseen"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: virhe luettaessa: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: virhe suljettaessa: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "SIJAINTI... - yhdistä SIJAINNIT oletustulosteeseen."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Yhdistä tietoja eri sijainneista ja tulosta ne oletussyötteeseen. Toimii "
+"aivan kuten perinteinen ohjelma cat, mutta käyttää gvfs-sijainteja "
+"paikallisten tiedostojen sijasta. Voit esimerkiksi käyttää sijaintia smb://"
+"server/resource/file.txt liitettävänä tiedostona."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Huomautus: putkita cat:n kautta, jos tarvitset sen muotoiluvalintoja kuten -"
+"n tai -T."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: sijainti puuttuu"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: virhe avattaessa sijaintia: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: virhe käynnistettäessä ohjelmaa: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "TIEDOSTOT... - avaa TIEDOSTOT rekisteröidyllä ohjelmalla."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Avaa tiedostot oletusohjelmalla, joka on rekisteröity avaamaan tämän "
+"tyyppiset tiedostot."
+
diff --git a/trunk/po/fr.po b/trunk/po/fr.po
new file mode 100644
index 00000000..6307f7f9
--- /dev/null
+++ b/trunk/po/fr.po
@@ -0,0 +1,1647 @@
+# French translation of gvfs.
+# Copyright (C) 2008-2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+#
+# Claude Paroz <claude@2xlibre.net>, 2008-2009.
+# Robert-André Mauchin <zebob.m@pengzone.org>, 2008.
+# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-14 16:00+0100\n"
+"PO-Revision-Date: 2009-02-14 16:16+0100\n"
+"Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
+"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"L'opération n'est pas prise en charge, les fichiers étant sur différents "
+"points de montage"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Valeur de retour de get_info non valide"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Valeur de retour de query_info non valide"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Impossible d'obtenir le descripteur de fichier du flux"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Valeur de retour de « open » non valide"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Le descripteur de fichier de flux n'a pas été obtenu"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Valeur de retour de « call » non valide"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Valeur de retour de get_filesystem_info non valide"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Impossible de trouver le point de montage hôte"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nom de fichier %s non valide"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Valeur de retour de query_filesystem_info non valide"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Valeur de retour de monitor_dir non valide"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Valeur de retour de monitor_file non valide"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "L'opération a été annulée"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Erreur du protocole de flux : %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Fin de flux"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "L'opération « seek » n'est pas prise en charge pour un flux"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "L'opération « query info » n'est pas prise en charge"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "L'opération « query info » n'est pas prise en charge pour un flux"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Erreur lors de l'obtention d'informations sur le point de montage : %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Erreur lors de la connexion au démon : %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Valeur de retour de open_icon_for_read non valide"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Erreur lors de la création du connecteur : %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Erreur lors de la connexion au connecteur : %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Format d'informations de fichier non valide"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Contenu de la liste d'information d'attribut non valide"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Erreur lors de l'initialisation d'Avahi : %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Erreur lors de la création du résolveur d'Avahi : %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Erreur de résolution du service %s « %s » dans le domaine « %s »"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Erreur de résolution du service %s « %s » dans le domaine « %s ». Un ou "
+"plusieurs enregistrements TXT manquent. Clés obligatoires : « %s »."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"Expiration de délai lors de la résolution du service %s « %s » dans le "
+"domaine « %s »"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "« %s » dns-sd encoded_triple mal formé"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Impossible de gérer la version %d du codage GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Données d'entrée non valides pour GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Erreur de connexion à D-Bus : %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Service %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Erreur : %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Utilisation : %s --spawner dbus-id chemin_objet"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Utilisation : %s clé=valeur clé=valeur ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Aucun type de montage indiqué"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "un point de montage pour %s est déjà en cours d'utilisation"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "erreur lors du démarrage du démon de montage"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ sur %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Aucun nom d'hôte indiqué"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Spécification de montage non valide"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Le fichier n'existe pas"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Le fichier n'est pas un répertoire"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Graver"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Impossible de créer un répertoire temporaire"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Ce fichier ou ce répertoire n'existe pas"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Répertoire non vide"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Impossible d'écraser un répertoire avec un fichier"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Créateur de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Le fichier existe"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Opération non prise en charge par le moteur"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Aucun fichier ou répertoire de ce nom dans le chemin cible"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Impossible d'écraser un répertoire avec un autre répertoire"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Le fichier cible existe"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Impossible de copier récursivement un répertoire"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Non pris en charge"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Impossible de se connecter au bus système"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Impossible de créer un contexte libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Impossible d'initialiser libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Aucun lecteur indiqué"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Impossible de trouver le lecteur %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Le lecteur %s ne contient pas de fichiers audio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "point de montage cdda sur %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disque audio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Le système de fichiers est occupé : %d fichier ouvert"
+msgstr[1] "Le système de fichiers est occupé : %d fichiers ouverts"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Aucun fichier nommé %s sur le lecteur %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Erreur provenant de « paranoia » sur le lecteur %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Erreur de déplacement dans le flux sur le lecteur %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Aucun fichier de ce nom"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Le fichier n'existe pas ou n'est pas une piste audio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Service de CD Audio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Poste de travail"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Système de fichiers"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Impossible d'ouvrir le répertoire"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Impossible d'ouvrir le fichier « montable »"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Erreur interne : %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Impossible de monter le fichier"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Aucun média dans le lecteur"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ce n'est pas un fichier pouvant être monté"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Impossible de démonter le fichier"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Impossible d'éjecter le fichier"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Erreur HTTP : %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Impossible d'analyser la réponse"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Réponse vide"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Réponse inattendue du serveur"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Réponse non valide"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Partage WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Saisissez le mot de passe pour %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Saisissez le mot de passe du serveur mandataire"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Ce partage ne prend pas en charge WebDAV"
+
+# Host
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "Partage WebDAV sur %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Impossible de créer la requête"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Le fichier cible existe déjà"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Le fichier a été modifié de manière externe"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "La création du fichier de sauvegarde a échoué"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Réseau local"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Impossible de surveiller le fichier ou répertoire."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Réseau"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Les comptes ne sont pris en charge"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "L'hôte a fermé la connexion"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Impossible d'ouvrir une connexion de données. Peut-être que votre pare-feu "
+"empêche cette action ?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Connexion de données fermée"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "L'opération a échoué"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Plus d'espace disponible sur le serveur"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Opération non prise en charge"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Accès refusé"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Type de page inconnu"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nom de fichier non valide"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Réponse non valide"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmission interrompue"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Impossible de se connecter à l'hôte"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Saisissez le mot de passe pour l'accès ftp sur %2s en tant que %1s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Saisissez le mot de passe pour l'accès ftp sur %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "La demande de saisie du mot de passe a été annulée"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp sur %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp en tant que %s sur %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Le fichier est un répertoire"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "les sauvegardes ne sont pas prises en charge pour le moment"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nom de fichier trop long"
+
+# L'utilisation de target serait peut-être plus homogène (Stéphane)
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nom de fichier de destination non valide"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s : %d : le répertoire ou le fichier existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s : %d : le répertoire ou le fichier n'existe pas"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s : %d : nom de fichier non valide"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s : %d : non pris en charge"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Appareil photo (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Appareil photo %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Lecteur audio %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Appareil photo"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Lecteur audio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Aucun périphérique indiqué"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Impossible de créer un contexte gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Erreur lors de la création de l'appareil photo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Erreur lors du chargement des informations du périphérique"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Erreur lors de la recherche d'informations du péripéhérique"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Erreur lors de l'obtention des informations du périphérique"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr ""
+"Erreur lors du paramétrage du port de communication de l'appareil photo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Erreur lors de l'initialisation de l'appareil photo"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "Montage de gphoto2 sur %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Aucun appareil photo indiqué"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Erreur de création de l'objet fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Erreur lors de l'obtention du fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Erreur lors de l'obtention des données du fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificateur d'icône « %s » malformé"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Erreur de déplacement dans le flux sur l'appareil photo %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ce n'est pas un répertoire"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "L'obtention de la liste des dossiers a échoué"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "L'obtention de la liste des fichiers a échoué"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Erreur lors de la création du répertoire"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Le nom existe déjà"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Nouveau nom trop long"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Erreur lors du renommage du répertoire"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Erreur lors du renommage du fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Répertoire « %s » non vide"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Erreur lors de la suppression du répertoire"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Erreur lors de la suppression du fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Impossible d'écrire dans le répertoire"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Impossible d'allouer un nouveau fichier à modifier"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Impossible de lire le fichier à modifier"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Impossible d'obtenir les données du fichier à modifier"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Erreur lors de l'écriture du fichier"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Non pris en charge (ce n'est pas le même répertoire)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+"Non pris en charge (la source est un répertoire, la destination un "
+"répertoire)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+"Non pris en charge (la source est un répertoire, la destination un fichier "
+"existant)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+"Non pris en charge (la source est un fichier, la destination un répertoire)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Erreur du client HTTP : %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codage non valide)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Les notifications de répertoires ne sont pas prises en charge"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Réseau Windows"
+
+# suggestions bienvenues, la traduction littérale me semble trop lourde
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Vue générale du réseau"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s sur %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "La prise en charge de l'USB est absente. Veuillez contacter votre fournisseur de logiciel"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Connexion au périphérique perdue"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Le périphérique requiert la mise à jour d'un logiciel"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Le programme ssh s'est terminé de manière inattendue"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nom d'hôte inconnu"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Pas de route vers l'hôte"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Connexion refusée par le serveur"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "La vérification de la clé de l'hôte a échoué"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Impossible de lancer le programme ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Impossible de lancer le programme ssh : %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Délai d'attente expiré lors de la connexion"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Saisissez la phrase de passe pour la clé"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Saisissez le mot de passe"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Impossible d'envoyer le mot de passe"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Se connecter malgré tout"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Annuler la connexion"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"L'identité de l'ordinateur distant (%s) est inconnue.\n"
+"Cela se produit lorsque vous vous connectez à un ordinateur pour la première "
+"fois.\n"
+"\n"
+"L'identité envoyée par l'ordinateur distant est %s. Si vous voulez être "
+"absolument certain qu'il est sûr de continuer, contactez votre "
+"administrateur système."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "La boîte de dialogue de connexion a été annulée."
+
+# envoyer à l'hôte ou identité de l'hôte ? j'ai un doute.
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Impossible d'envoyer la confirmation de l'identité de l'hôte"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Erreur de protocole"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp en tant que %s sur %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp sur %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Impossible de trouver une commande ssh prise en charge"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Échec"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Réponse non valide reçue"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id « %s » non valide dans OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Erreur de création du fichier de sauvegarde : %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Impossible de créer un fichier temporaire"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Impossible de déplacer un répertoire sur un répertoire de même nom"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Un mot de passe doit être saisi pour accéder au partage %s sur %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Erreur interne (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Impossible de monter le partage Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Type « seek » non pris en charge"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "La création du fichier de sauvegarde a échoué : %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Erreur lors de la suppression du fichier : %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Erreur lors du déplacement du fichier : %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Erreur lors de la suppression du fichier cible : %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Impossible de déplacer un répertoire de façon récursive"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Service de partage Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Un mot de passe doit être saisi pour accéder à %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Partages Windows sur %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "L'obtention de la liste des partages du serveur a échoué"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Le fichier n'est pas « montable »"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ce n'est pas un fichier standard"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Service de partage Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Le dossier de la corbeille ne peut pas être supprimé"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Les éléments dans la corbeille ne peuvent pas être modifiés"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Corbeille"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Type de moteur non valide"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Erreur lors de l'envoi du fd : %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Les liens symboliques ne sont pas pris en charge par le moteur"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Message dbus non valide"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Remplace l'ancien démon."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Ne démarre pas « fuse »."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Démon GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Démon principal pour GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s : %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Essayez « %s --help » pour obtenir plus d'informations."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Paramètres non valides en provenance du fils lancé"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Le montage automatique a échoué : %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "L'emplacement indiqué n'est pas monté"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "L'emplacement indiqué n'est pas pris en charge"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "L'emplacement est déjà monté"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "L'emplacement n'est pas « montable »"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disque CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disque CD-ROM vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disque CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disque CD-R vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disque CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disque CD-RW vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disque DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disque DVD-ROM vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disque DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disque DVD-RAM vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disque DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disque DVD-RW vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disque DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disque DVD+R vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disque DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disque DVD+RW vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disque DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disque DVD+R DL vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disque Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disque Blu-Ray vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disque Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disque Blu-Ray R vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disque Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disque Blu-Ray RW vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disque HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disque HD DVD vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disque HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disque HD DVD-R vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disque HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disque HD DVD-RW vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disque MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disque MO vierge"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disque"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disque vierge"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Lecteur %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Lecteur %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Lecteur de disquettes"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Disque RAID logiciel"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Lecteur USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Disque ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Disque SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Disque FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Lecteur de bande"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Lecteur Compact Flash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Lecteur Memory Stick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Lecteur Smart Media"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Lecteur SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Lecteur Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Lecteur Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Clé USB"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Lecteur de stockage de masse"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"L'éjection du média a échoué ; un ou plusieurs volumes sont en cours "
+"d'utilisation sur le média."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f Kio"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f Mio"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f Gio"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disque mixte audio/données"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Média %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Données chiffrées %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s : %s : erreur d'ouverture du fichier : %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s : %s, erreur d'écriture sur stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s : %s : erreur de lecture : %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s : %s : erreur de fermeture : %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "EMPLACEMENT... - concatène les EMPLACEMENTS vers la sortie standard."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatène les fichiers spécifiés par les emplacements et les affiche sur la "
+"sortie standard. Le principe est identique à l'utilitaire traditionnel "
+"« cat », excepté l'utilisation d'emplacements gvfs au lieu de fichiers "
+"locaux. Par exemple, il est possible d'indiquer quelque chose comme smb://"
+"serveur/ressource/fichier.txt comme emplacement à concaténer."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Note : il suffit de rediriger sur « cat » si vous avez besoin d'options de "
+"formatage telles que -n, -T ou d'autres."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s : emplacements manquants"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s : %s : erreur d'ouverture d'un emplacement : %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s : %s : erreur de lancement d'une application : %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FICHIERS... - ouvre les FICHIERS avec l'application répertoriée."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Ouvre chaque fichier avec l'application enregistrée pour gérer par défaut le "
+"type de fichier."
+
diff --git a/trunk/po/ga.po b/trunk/po/ga.po
new file mode 100644
index 00000000..98b3b3d0
--- /dev/null
+++ b/trunk/po/ga.po
@@ -0,0 +1,1524 @@
+# Irish translations for gvfs package.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+# Seán de Búrca <leftmostcat@gmail.com>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-28 20:52-0400\n"
+"PO-Revision-Date: 2008-08-28 20:52-0500\n"
+"Last-Translator: Seán de Búrca <leftmostcat@gmail.com>\n"
+"Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=5; plural=n==1 ? 0 : (n%10==1 || n%10==2) ? 1 : (n%"
+"10>=3 && n%10<= 6) ? 2 : ((n%10>=7 && n%10<=9) || n==10) ? 3 : 4;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:757
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr ""
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Earráid: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ ar %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr ""
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Dóigh"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, c-format
+msgid "No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Cruthaitheoir CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Target file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Cannot initialize libhal"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Diosca Fuaime"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr ""
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Ríomhaire"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Córas Comhad"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+msgid "Can't open directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Earráid HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV ar %s"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Líonra"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp ar %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp mar %s ar %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ainm comhaid neamhbhailí"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Ceamara Digiteach (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Ceamara %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Seinnteoir Fuaime %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Ceamara"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Seinnteoir Fuaime"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+msgid "Failed to get folder list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+msgid "Error creating camera"
+msgstr "Earráid agus ceamara á chruthú"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+msgid "Error loading device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+msgid "Error getting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2080
+msgid "Failed to get file list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+msgid "Error creating directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+msgid "Name already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+msgid "New name too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+msgid "Error deleting directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+msgid "Can't write to directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+msgid "Not supported (not same directory)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ionchódú neamhbhailí)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr ""
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Líonra Windows"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Líonra Logánta"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "%s ar %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Logáil Isteach Mar Sin Féin"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Cealaigh Logáil Isteach"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr ""
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp ar %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr ""
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Earráid agus comhad á scriosadh: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Earráid agus comhad á bhogadh: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr ""
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Bruscar"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (sa bhruscar)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr ""
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Earráid agus fd á sheoladh: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr ""
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Deamhan GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Tiomántán %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Tiomántán %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Tiomántán Flapach"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Tiomántán RAID Bogearraí"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Tiomántán USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Tiomántán ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Tiomántán SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Tiomántán FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tiomántán Téipe"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Tiomántán CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Tiomántán MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Tiomántán SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Tiomántán SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Tiomántán Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Tiomántán Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Méaróg Chuimhne"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Tiomántán Ollstórála"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+msgid "Mixed Audio/Data Disc"
+msgstr "Diosca Fuaime/Sonraí Measctha"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, c-format
+msgid "%s Media"
+msgstr "%s Meáin"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s Sonraí Criptithe"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Diosca CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Diosca CD-ROM Bán"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Diosca CD-R"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Diosca CD-R Bán"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Diosca CD-RW"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Diosca CD-RW Bán"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Diosca DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Diosca DVD-ROM Bán"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Diosca DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Diosca DVD-RAM Bán"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Diosca DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Diosca DVD-RW Bán"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Diosca DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Diosca DVD+R Bán"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Diosca DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Diosca DVD+RW Bán"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Diosca DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Diosca DVD+R DL Bán"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Diosca Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Diosca Blu-Ray Bán"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Diosca Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Diosca Blu-Ray R Bán"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Diosca Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Diosca Blu-Ray RW Bán"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Diosca HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Diosca HD DVD Bán"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Diosca HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Diosca HD DVD-R Bán"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Diosca HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Diosca HD DVD-RW Bán"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Diosca MO"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Diosca MO Bán"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Diosca"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Diosca Bán"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: earráid agus comhad á oscailt: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, earráid agus stdout á scríobh"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: earráid agus á léamh: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: earráid agus á dhúnadh: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
diff --git a/trunk/po/gl.po b/trunk/po/gl.po
new file mode 100644
index 00000000..f289420b
--- /dev/null
+++ b/trunk/po/gl.po
@@ -0,0 +1,1596 @@
+# translation of gl.po to Galego
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Ignacio Casal Quinteiro <icq@svn.gnome.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gl\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-21 17:47+0200\n"
+"PO-Revision-Date: 2008-08-21 17:48+0200\n"
+"Last-Translator: Ignacio Casal Quinteiro <icq@svn.gnome.org>\n"
+"Language-Team: Galego <proxecto@trasno.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"A operación non está soportada, os ficheiros están en diferentes puntos de "
+"montaxe"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "Non se puido obter o descritor do ficheiro de fluxo"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr "open devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr "Non se puido obter un descritor do ficheiro de fluxo"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info devolveu un valor non válido"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Non se puido encontrar o punto de montaxe anexado"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nome de ficheiro non válido %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir devolveu un valor non válido"
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file devolveu un valor non válido"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Erro no protocolo de fluxo: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Final do fluxo"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "A operación foi cancelada"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Non se permite buscar no fluxo"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "A operación de consulta de información non está soportada"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Non se soporta consulta de información en fluxo"
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Erro ao obter a información de montaxe: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Erro ao conectar co daemon: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Erro creando o socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Erro ao conectar co socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Formato de información do ficheiro non válido"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "O contido da lista de información do atributo non é válido"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Erro ao conectar a D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Servizo de sistema de ficheiros %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Erro: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Uso: %s --spawner dbus-id ruta_ao_obxecto"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Uso: %s clave=valor clave=valor ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Non se especificou o tipo de montaxe"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "o punto de montaxe para %s xa se está usando"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "erro ao iniciar o daemon de montaxe"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ en %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Non se especificou un nome de servidor"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1449 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr "Especificación de montaxe non válida"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "O ficheiro non existe"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "O ficheiro non é un directorio"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Gravar"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Imposible crear o directorio temporal"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "No such file or directory"
+msgstr "O ficheiro ou directorio non existe"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2036
+msgid "Directory not empty"
+msgstr "O directorio non está baleiro"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr "Non se pode copiar un ficheiro sobre un directorio"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Creador de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2763
+msgid "File exists"
+msgstr "O ficheiro xa existe"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr "O ficheiro ou directorio non existe na ruta de destino"
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr "Non se pode copiar un directorio sobre outro directorio"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Target file exists"
+msgstr "O ficheiro obxectivo existe"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr "Non se pode copiar recursivamente o directorio"
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2348
+#: ../daemon/gvfsbackendgphoto2.c:2556 ../daemon/gvfsbackendgphoto2.c:2651
+#: ../daemon/gvfsbackendgphoto2.c:2742
+msgid "Not supported"
+msgstr "Non soportado"
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot connect to the system bus"
+msgstr "Non se pode conectar ao bus do sistema"
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot create libhal context"
+msgstr "Non se pode crear o contexto libhal"
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1427
+msgid "Cannot initialize libhal"
+msgstr "Non se pode inicializar libhal"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr "Non se especificou unha unidade"
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Non se pode encontrar a unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "A unidade %s non contén ficheiros de son"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda montado en %s"
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Disco de son"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1655
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "O sistema de ficheiros está ocupado: %d ficheiro aberto"
+msgstr[1] "O sistema de ficheiros está ocupado: %d ficheiros abertos"
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "O ficheiro %s non existe na unidade %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Erro de 'paranoia' na unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Erro ao buscar no fluxo na unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1711
+#, c-format
+msgid "No such file"
+msgstr "Non existe o ficheiro"
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "O ficheiro non existe ou non é unha pista de son"
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr "Servizo de sistema de ficheiros de CD de son"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computador"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistema de ficheiros"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1703
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+msgid "Can't open directory"
+msgstr "Non se pode abrir o directorio"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "Non se pode abrir o ficheiro montable"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Erro interno: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "Non se pode montar o ficheiro"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "Non hai ningún medio na unidade"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Non é un ficheiro montable"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "Non se pode desmontar o ficheiro"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "Non se pode expulsar o ficheiro"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1516
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Erro de HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "Non se puido analizar a resposta"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Resposta baleira"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Resposta inesperada do servidor"
+
+#: ../daemon/gvfsbackenddav.c:1149 ../daemon/gvfsbackenddav.c:1651
+msgid "Response invalid"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackenddav.c:1292
+msgid "WebDAV share"
+msgstr "Compartición WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1294
+#, c-format
+msgid "Enter password for %s"
+msgstr "Introduza contrasinal para %s"
+
+#: ../daemon/gvfsbackenddav.c:1297
+msgid "Please enter proxy password"
+msgstr "Introduza o contrasinal do proxy"
+
+#: ../daemon/gvfsbackenddav.c:1520 ../daemon/gvfsbackenddav.c:1524
+msgid "Not a WebDAV enabled share"
+msgstr "Non é unha compartición activada WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1547
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV en %s"
+
+#: ../daemon/gvfsbackenddav.c:1607 ../daemon/gvfsbackenddav.c:1680
+msgid "Could not create request"
+msgstr "Non se puido crear a resposta"
+
+#: ../daemon/gvfsbackenddav.c:1743 ../daemon/gvfsbackenddav.c:1996
+#: ../daemon/gvfsbackenddav.c:2107 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr "O ficheiro obxectivo xa existe"
+
+#: ../daemon/gvfsbackenddav.c:1816 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr "O ficheiro foi modificado externamente"
+
+#: ../daemon/gvfsbackenddav.c:1847 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr "Fallou a creación do ficheiro de seguranza"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Non se pode monitorizar ficheiros ou directorios."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Rede"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "As contas non están soportadas"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "O servidor pechou a conexión"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Non se pode abrir a conexión de datos. Pode ser que esté a través dun "
+"firewall?"
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "Conexión de datos pechada"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Fallou a operación"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "Sen espazo no servidor"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Operación non soportada"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Permiso denegado"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "Tipo de páxina descoñecida"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Nome de ficheiro inválido"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "transmisión rota"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "Non se puido conectar ao servidor"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Introduza o contrasinal para ftp en %s"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Cancelouse o diálogo do contrasinal"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp en %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp como %s en %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "O ficheiro é un directorio"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "as copias de seguranza non están soportadas todavía"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "o nome de ficheiro é demasiado longo"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "Nome de ficheiro de destino inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: O directorio ou ficheiro existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: O ficheiro ou directorio non existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Nome de ficheiro inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Non soportado"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Cámara dixital (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Cámara %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Reprodutor de son %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Reprodutor de son"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get folder list"
+msgstr "Fallou ao obter a lista de cartafoles"
+
+#: ../daemon/gvfsbackendgphoto2.c:1442
+msgid "No device specified"
+msgstr "Non se especificou ningún dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1459
+msgid "Cannot create gphoto2 context"
+msgstr "Non se pode crear o contexto gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469
+msgid "Error creating camera"
+msgstr "Erro creando a cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1482 ../daemon/gvfsbackendgphoto2.c:1492
+msgid "Error loading device information"
+msgstr "Erro ao cargar a información do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1504
+msgid "Error looking up device information"
+msgstr "Erro ao buscar a información do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error getting device information"
+msgstr "Erro ao obter a información do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1527
+msgid "Error setting up camera communications port"
+msgstr "Erro ao configurar o porto de comunicacións da cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1538
+msgid "Error initializing camera"
+msgstr "Erro ao inicializar a cámara"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1552
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 montado en %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1627
+msgid "No camera specified"
+msgstr "Non se especificou ningunha cámara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error creating file object"
+msgstr "Erro ao crear o ficheiro obxecto"
+
+#: ../daemon/gvfsbackendgphoto2.c:1733
+msgid "Error getting file"
+msgstr "Erro ao obter o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:1742
+msgid "Error getting data from file"
+msgstr "Erro ao obter datos do ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:1836 ../daemon/gvfsbackendgphoto2.c:3010
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Erro ao buscar no fluxo na cámara %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1975 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Non é un directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2071
+msgid "Failed to get file list"
+msgstr "Fallou ao obter a lista de ficheiros"
+
+#: ../daemon/gvfsbackendgphoto2.c:2360
+msgid "Error creating directory"
+msgstr "Erro ao crear o directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2568
+msgid "Name already exists"
+msgstr "O nome xa existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2579 ../daemon/gvfsbackendgphoto2.c:3200
+msgid "New name too long"
+msgstr "O nome é demasiado longo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2589 ../daemon/gvfsbackendgphoto2.c:3211
+msgid "Error renaming dir"
+msgstr "Erro ao renomear o directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2601 ../daemon/gvfsbackendgphoto2.c:3223
+msgid "Error renaming file"
+msgstr "Erro ao renomear o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:2664
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "O directorio '%s' non está baleiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:2675
+msgid "Error deleting directory"
+msgstr "Erro ao eliminar o directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "Error deleting file"
+msgstr "Erro ao eliminar o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:2752
+msgid "Can't write to directory"
+msgstr "Non se pode escribir no directorio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2799
+msgid "Cannot allocate new file to append to"
+msgstr "Non se pode asignar o novo ficheiro no que engadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2813
+msgid "Cannot read file to append to"
+msgstr "Non se pode ler o ficheiro no que engadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:2823
+msgid "Cannot get data of file to append to"
+msgstr "Non se poden obter os datos do ficheiro no que engadir"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Error writing file"
+msgstr "Erro ao escribir o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:3156
+msgid "Not supported (not same directory)"
+msgstr "Non soportado (non é o mesmo directorio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3168
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Non soportado (src é un directorio, dst é un directorio)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3176
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Non soportado (src é un directorio, dst é un ficheiro existente)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Non soportado (src é un ficheiro, dst é un directorio)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Erro HTTP do cliente: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codificación inválida)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Non se soporta a notificación de directorios"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Rede de Windows"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Rede local"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Monitor de localización de rede"
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "%s en %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "Perdeuse a conexión co dispositivo"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "O dispositivo require unha actualización de software"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "O programa de ssh rematou inesperadamente"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Nome de servidor descoñecido"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Non hai ruta ao servidor"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "Conexión rexeitada polo servidor"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Fallou a verificación da chave do servidor"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "Non se pode lanzar o programa ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Non se pode lanzar o programa ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Expirou o tempo para iniciar a sesión"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Introduza unha frase de paso para a chave"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Introduza contrasinal"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "Non se pode enviar o contrasinal"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Iniciar de todas maneiras"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Cancelar inicio"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"A identidade do computador remoto (%s) é descoñecida.\n"
+"Isto pasa cando inicia sesión nun computador a primeira vez.\n"
+"\n"
+"A identidade enviada polo computador remoto é %s. Se quere estar "
+"completamente seguro de que é seguro continuar, contacto co administrador do "
+"sistema."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Diálogo de inicio cancelado"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "Non se pode enviar a confirmación de identidade de host"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Erro de protocolo"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp en %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "Non se pode encontrar o comando ssh soportado"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Fallo"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "Recibiuse unha resposta inválida"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Erro ao crear o ficheiro de seguranza: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "Non se pode crear o ficheiro temporal"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr "Non se pode mover un directorio sobre un directorio"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Necesítase contrasinal para a compartición %s en %s"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Erro interno (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr "Fallou ao montar a compartición Windows"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr "Tipo de busca non soportada"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Fallou a creación do ficheiro de seguranza: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Erro ao borrar o ficheiro: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Erro ao mover o ficheiro: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Erro ao eliminar o ficheiro obxectivo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr "Non se pode mover recursivamente un directorio"
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr "Servizo do sistema de ficheiros compartidos de Windows"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Comparticións Windows en %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "O ficheiro non se pode montar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Non é un ficheiro regular"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Servizo de sistema de ficheiros de rede de Windows"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Lixo"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (no colector de lixo)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "Non se pode borrar o lixo"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Non se soporta a notificación do lixo"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipo de backend inválido"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Erro ao enviar o descritor de ficheiro: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "O backend non soporta a operación"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "O backend non soporta ligazóns simbólicas"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "Mensaxe de dbus inválida"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Substitúe o daemon antigo."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Non iniciar fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Daemon GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Daemon principal para GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Tente \"%s --help\" para máis información."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "Argumentos non válidos para o fillo lanzado"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Fallou automount: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "A localización especificada non está montada"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "A localización especificada non está soportada"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "A localización xa está montada"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "A localización non é montable"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unidade %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unidade %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disquetera"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unidade RAID por software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unidade USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Unidade ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Unidade SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unidade FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unidade de cinta"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unidade CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unidade MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unidade SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unidade SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unidade Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unidade Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Unidade Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unidade de almacenamento masivo"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Fallou ao expulsar o medio, un ou máis volumes está ocupados no medio."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+msgid "Mixed Audio/Data Disc"
+msgstr "Disco de son e datos"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, c-format
+msgid "%s Media"
+msgstr "Medio %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Datos cifrados %s"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disco CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disco CD-ROM en branco"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disco CD-R"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disco CD-R en branco"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disco CD-RW"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disco CD-RW en branco"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disco DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disco DVD-ROM en branco"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disco DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disco DVD-RAM en branco"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disco DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disco DVD-RW en branco"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disco DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disco DVD+R en branco"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disco DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disco DVD+RW en branco"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disco DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disco DVD+R DL en branco"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disco Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disco Blu-Ray en branco"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R en branco"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW en branco"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disco HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disco HD DVD en branco"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disco HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disco HD DVD-R en branco"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disco HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disco HD DVD-RW en branco"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disco MO"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disco MO en branco"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Disco"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disco en branco"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: erro ao abrir o ficheiro: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, erro ao escribir en stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: erro ao ler: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: erro ao pechar: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCALIZACIÓN... - concatenar as LOCALIZACIÓNS cunha saída estándar."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenar ficheiro e localizacións e imprimilos na saída estándar. Funciona "
+"igual que a utilidade tradicional 'cat', pero usando a localización gvfs no "
+"lugar dos ficheiros locais: por exemplo, pode usar algo como smb://server/"
+"resource/file.txt coma unha localización para concatenar."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: use unha tubería a través de cat se necesita as opcións de formato "
+"tales coma -n, -T ou outras."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: faltan localizacións"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: erro ao abrir a localización: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: erro ao lanzar a aplicación: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FICHEIROS... - abrir FICHEIROS cunha aplicación rexistrada."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Abre o ficheiro(s) cunha aplicación rexistrada predeterminada para manexar o "
+"tipo do ficheiro."
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr "Erro ao listar os cartafoles para averiguar o prefixo de ignorado"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "Erro ao crear a listaxe de información do porto"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr ""
+#~ "Erro ao obter a información do porto da listaxe de información do porto"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "O sistema de ficheiros está ocupado: %d ficheiros abertos"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Erro ao listar os cartafoles"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "Erro ao listar os ficheiros no cartafol"
+
+#~ msgid "File unavailable"
+#~ msgstr "Ficheiro non dispoñible"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Medio %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Medio %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Medio %.1f GB"
+
+#~ msgid "Invalid reply from server."
+#~ msgstr "Resposta inválida do servidor."
+
+#~ msgid "Operation cancelled"
+#~ msgstr "Operación cancelada"
+
+#~ msgid "Invalid username"
+#~ msgstr "Nome de usuario inválido"
+
+#~ msgid "Invalid password"
+#~ msgstr "Contrasinal inválido"
+
+#~ msgid "FTP on %s"
+#~ msgstr "FTP en %s"
+
+#~ msgid "FTP on %s:%u"
+#~ msgstr "FTP en %s:%u"
+
+#~ msgid "The file does not exist"
+#~ msgstr "O ficheiro non existe"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Disco de son en %s"
diff --git a/trunk/po/gu.po b/trunk/po/gu.po
new file mode 100644
index 00000000..4a9c115a
--- /dev/null
+++ b/trunk/po/gu.po
@@ -0,0 +1,1612 @@
+# translation of gvfs.HEAD.gu.po to Gujarati
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Sweta Kothari <swkothar@redhat.com>, 2008, 2009.
+# Ankit Patel <ankit@redhat.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD.gu\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-27 15:51+0000\n"
+"PO-Revision-Date: 2009-03-15 11:42+0530\n"
+"Last-Translator: Ankit Patel <ankit@redhat.com>\n"
+"Language-Team: Gujarati <fedora-trans-gu@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "ક્રિયા એ આધારભૂત નથી. વિવિધ માઉન્ટો પર ફાઇલો"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "સ્ટ્રીમ ફાઇલ વર્ણનકર્તા મેળવી શકાતી નથી"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "ખોલવામાંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "સ્ટ્રીમ ફાઇલ વર્ણનકર્તા મળી નહિં"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "કોલ માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "બંધ કરવામાં આવી રહ્યુ માઉન્ટ શોધી શકાયુ નહિં"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "અયોગ્ય ફાઇલનામ %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:628
+#: ../client/gdaemonfileinputstream.c:781
+#: ../client/gdaemonfileinputstream.c:899
+#: ../client/gdaemonfileinputstream.c:1147
+#: ../client/gdaemonfileinputstream.c:1389
+#: ../client/gdaemonfileoutputstream.c:504
+#: ../client/gdaemonfileoutputstream.c:679
+#: ../client/gdaemonfileoutputstream.c:871
+#: ../client/gdaemonfileoutputstream.c:1050
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+msgid "Operation was cancelled"
+msgstr "ક્રિયા કાઢી નંખાયેલ હતી"
+
+#: ../client/gdaemonfileinputstream.c:525
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1680
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:448
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1232
+#: ../client/gdaemonfileoutputstream.c:1242
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "સ્ટ્રીમ પ્રોટોકોલમાં ભૂલ: %s"
+
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1242
+msgid "End of stream"
+msgstr "સ્ટ્રીમનો અંત"
+
+#: ../client/gdaemonfileinputstream.c:1328
+#: ../client/gdaemonfileoutputstream.c:979
+msgid "Seek not supported on stream"
+msgstr "સ્ટ્રીમ પર સીક આધારભૂત નથી"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "જ્યારે માઉન્ટ જાણકારી મેળવી રહ્યા હોય ત્યારે ભૂલ: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "ડેમનને જોડી રહ્યા હોય ત્યારે ભૂલ: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read માંથી અયોગ્ય પાછી મળેલી કિંમત"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "સોકેટ ને બનાવી રહ્યા હોય ત્યારે ભૂલ: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "સોકેટ ને જોડી રહ્યા હોય ત્યારે ભૂલ: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "અયોગ્ય ફાઇલ જાણકારી બંધારણ"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "અયોગ્ય લક્ષણ જાણકારી યાદી સમાવિષ્ટ"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error initializing camera"
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi નો આરંભ કરતી વખતે ભૂલ: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating backup file: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi ઉકેલનાર બનાવતી વખતે ભૂલ: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" સેવા \"%s\" ને ડોમેઈન \"%s\" પર ઉકેલતી વખતે ભૂલ"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr "\"%s\" સેવા \"%s\" ને ડોમેઈન \"%s\" પર ઉકેલતી વખતે ભૂલ. એક અથવા વધુ TXT રેકોર્ડો ગુમ થયેલ છે. કીઓ જરૂરી: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" સેવા \"%s\" ને ડોમેઈન \"%s\" પર ઉકેલવાનો સમય સમાપ્ત"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "મલીન dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon સંગ્રહપદ્ધતિની %d આવૃત્તિ સંભાળી શકતા નથી"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon માટે મલીન ઈનપુટ માહિતી"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus માં ભૂલ જોડાઇ રહી છે: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ફાઇલસિસ્ટમ સેવા"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ભૂલ: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "વપરાશ: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "વપરાશ: %s કી=કિંમત કી=કિંમત ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "માઉનટ પ્રકાર સ્પષ્ટ થયેલ નથી"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s પહેલેથી જ ચાલી રહ્યુ છે તે માટે માઉન્ટપોઇંટ"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "ભૂલ માઉન્ટ ડેઇમોનમાં શરૂ થઇ રહી છે"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "/ on %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "યજમાનનામ સ્પષ્ટ થયેલ નથી"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "અયોગ્ય માઉન્ટ સ્પષ્ટીકરણ"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ફાઇવ અસ્તિત્વ ધરાવતી નથી"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "ફાઇલ એ ડિરેક્ટરી નથી"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "બર્ન"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "કામચલાઉ ડિરેક્ટરી બનાવવા માટે અસમર્થ"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "આવી ફાઇલ અથવા ડિરેક્ટરી નથી"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "ડિરેક્ટરી ખાલી નથી"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ડિરેક્ટરી ઉપર ફાઇલને નકલ કરી શકાતી નથી"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD બનાવનાર"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "ફાઇલ અસ્તિત્વ ધરાવે છે"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "બેકએન્ડ દ્દારા ક્રિયા આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "લક્ષ્ય માર્ગમાં આવી ફાઇલ અથવા ડિરેક્ટરી નથી"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "ડિરેક્ટરી ઉપર ડિરેક્ટરીની નકલ કરી શકાતી નથી"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "લક્ષ્ય ફાઇલ અસ્તિત્વ ધરાવે છે"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "ડિરેક્ટરી નકલને પુનરાવર્તિત કરી શકાતી નથી"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "સિસ્ટમ બસથી જોડાણ થઇ શકતુ નથી"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "લિબહાલ સંદર્ભને બનાવી શકાતો નથી"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "લિબહાલની શરૂઆત કરી શકાતી નથી"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "ડ્રાઇવ સ્પષ્ટ થયેલ નથી"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ડ્રાઇવ %s શોધી શકાતી નથી"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ડ્રાઇવ %s ઓડિયો ફાઇલોને સમાવતુ નથી"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s પર cdda માઉન્ટ"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "ઓડિયો ડિસ્ક"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ફાઇલ સિસ્ટમ વ્યસ્ત છે: %d ખુલ્લી ફાઇલ"
+msgstr[1] "ફાઇલ સિસ્ટમ વ્યસ્ત છે: %d ખુલ્લી ફાઇલો"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ડ્રાઇવ %s પર આવી ફાઇલ %s નથી"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ડ્રાઇવ %s પર 'paranoia' માંથી ભૂલ"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ડ્રાઈવ %s પર સ્ટ્રીમમાં પહોંચવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "આવી ફાઇલ નથી"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ફાઈલ અસ્તિત્વમાં નથી અથવા ઓડિયો ટ્રેક નથી"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "ઓડિયો CD ફાઇલસિસ્ટમ સેવા"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "કમ્પ્યુટર"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ફાઇલસિસ્ટમ"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "ડિરેક્ટરીને ખોલી શકાતી નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "માઉન્ટ કરી શકાય તેવી ફાઈલ ખોલી શકતા નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "આંતરિક ભૂલ: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ફાઇલ માઉન્ટ કરી શકાતી નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ડ્રાઇવમાં મીડિયા નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "માઉન્ટ કરી શકાય તેવી ફાઈલ નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ફાઇલને અનમાઉન્ટ કરી શકાતી નથી"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ફાઇલને કાઢી શકાતી નથી"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ભૂલ: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "જવાબનું પદચ્છેદન કરી શકાતુ નથી"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "ખાલી જવાબ"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "સર્મર માંથી અનિચ્છનીય જવાબ"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "જવાબ અયોગ્ય"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV હિસ્સો"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s માટે પાસવર્ડ નો પ્રવેશ કરો"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "મહેરબાની કરીને પ્રોક્સી પાસવર્ડનો પ્રવેશ કરો"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV સક્રિયકૃત વહેંચણી નથી"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s પર WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "માગણી બનાવી શકાતી નથી"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "લક્ષ્ય ફાઇલ પહેલીથી જ હાજર છે"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "ફાઇલ એ બહારથી બદલાયેલ છે"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "બેકઅપ ફાઇલને બનાવવામાં નિષ્ફળતા"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "સ્થાનીય નેટવર્ક"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ફાઇલ અથવા ડિરેક્ટરીને મોનિટર કરી શકાતી નથી"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "નેટવર્ક"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "ખાતાઓ આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "યજમાન બંધ કરાયેલ જોડાણ"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "માહિતી જોડાણ ખોલી શકાતુ નથી. કદાચ તમારુ ફાયરવોલ આને અટકાવે છે?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "માહિતી જોડાણ બંધ થયેલ છે"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "ક્રિયા નિષ્ફળ થયેલ છે"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "સર્વર પર જગ્યા બાકી નથી"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "ક્રિયા આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "પરવાનગી ઇન્કાર કરેલ છે"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "પાનું પ્રકાર અજાણ્યો"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "અયોગ્ય ફાઇલનામ"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "અયોગ્ય જવાબ"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "ખંડિત થયેલ પ્રસારણ"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "યજમાનને જોડાણ કરી શકાતુ નથી"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "%s પર %s તરીકે ftp માટે પાસવર્ડ દાખલ કરો"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s પર ftp માટે પાસવર્ડ દાખલ કરો"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "પાસવર્ડ સંવાદ રદ કરાયેલ છે"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s પર ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s પર %s તરીકે ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "ફાઇલ એ ડિરેક્ટરી છેા"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "હજુ બેકઅપ આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ફાઇલનામ ઘણુ લાંબુ છે"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "અયોગ્ય લક્ષ્ય ફાઇલનામ"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ડિરેક્ટરી અથવા ફાઇલ અસ્તિત્વ ધરાવે છે"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: આવી ફાઇલ અથવા ડિરેક્ટરી નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: અયોગ્ય ફાઇલનામ"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: આધારભૂત નથી"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ડિજિટલ કેમેરા (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s કેમેરા"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ઓડિયો પ્લેયર"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "કેમેરા"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "ઓડિયો પ્લેયર"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "ઉપકરણ સ્પષ્ટ થયેલ નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 સંદર્ભ બનાવી શકાતો નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "કેમેરા બનાવી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "ઉપકરણ જાણકારી ને લોડ કરી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "ઉપકરણ જાણકારી ને જોઇ રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "ઉપકરણની જાણકારી મેળવી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+#| msgid "Error setting port info"
+msgid "Error setting up camera communications port"
+msgstr "કેમેરા સંપર્કવ્યવહાર પોર્ટ સુયોજીત કરવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "કેમેરાને શરૂ કરી રહ્યા હોય ત્યારે ભૂલ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s પર gphoto2 માઉન્ટ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "કેમેરા સ્પષ્ટ થયેલ નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "ફાઇલ ઓબ્જેક્ટને બનાવી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "ફાઇલ મેળવી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "ફાઇલમાંથી માહિતી મેળવી રહ્યા હોય ત્યારે ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "મલીન ચિહ્ન ઓળખનાર '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "કેમેરા %s પર સ્ટ્રીમમાં પહોંચવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "ડિરેક્ટરી નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "ફોલ્ડર યાદીને મેળવવામાં નિષ્ફળતા"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "ફાઇલ યાદીને મેળવવામાં નિષ્ફળતા"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "ડિરેક્ટરી બનાવવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "નામ પહેલેથી જ અસ્તિત્વ ધરાવે છે"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "નવુ નામ ઘણુ લાંબુ છે"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "ડિરેક્ટરીને ફરીથી નામ આપવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "ફાઇલને ફરીથી નામ આપવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "ડિરેક્ટરી '%s' ખાલી નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "ડિરેક્ટરી દૂર કરવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "ફાઇલ દૂર કરવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "ડિરેક્ટરીને લખી શકાતી નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "ઉમેરવા માટે નવી ફાઈલ ફાળવી શકતા નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "ઉમેરવા માટે ફાઈલ વાંચી શકતા નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "ઉમેરવા માટે ફાઈલની માહિતી મેળવી શકતા નથી"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "ફાઇલ લખવામાં ભૂલ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "આધારભૂત નથી (ડિરેક્ટરી એજ નથી)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "આધારભૂત નથી (src એ ડિરેક્ટરી છે, dst એ ડિરેક્ટરી છે)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "આધારભૂત નથી (src ડિરેક્ટરી છે, dst એ અસ્તિત્વ ધરાવતી ફાઇલ છે)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "આધારભૂત નથી (src ફાઇલ છે, dst ડિરેક્ટરી છે)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP ક્લાઇન્ટ ભૂલ: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (અયોગ્ય એનકોડીંગ)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ડિરેક્ટરી સૂચન આધારભૂત નથી"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "વિન્ડો નેટવર્ક"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "નેટવર્ક જગ્યા મોનિટર"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s પર %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB આધાર ગુમ થયેલ છે. મહેરબાની કરીને તમારા સોફ્ટવેર વિક્રેતાનો સંપર્ક કરો."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "ઉપકરણનું જોડાણ નષ્ટ થઈ ગયું"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "ઉપકરણ ને સોફ્ટવેર સુધારાની જરૂર છે"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh કાર્યક્રમ અનિચ્છનીય રીતે બંધ થઈ ગયો"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "યજમાનનામ જાણીતુ નથી"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "યજમાનને રુટ નથી"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "સર્વર દ્વારા જોડાણ રદ થઈ ગયું"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "યજમાન કી ચકાસવામાં નિષ્ફળતા"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh કાર્યક્રમ પેદા કરવામાં અસમર્થ"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh કાર્યક્રમ પેદા કરવામાં અસમર્થ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr "પ્રવેશ કરતી વખતે સમય સમાપ્ત"
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr "કી માટે પાસફ્રેઝ દાખલ કરો"
+
+#: ../daemon/gvfsbackendsftp.c:857
+msgid "Enter password"
+msgstr "પાસવર્ડને દાખલ કરો"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "પાસવર્ડ મોકલી શકાતો નથી"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "કોઇપણ રીતે પ્રવેશો"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Cancel Login"
+msgstr "પ્રવેશ ને રદ કરો"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"દૂરસ્થ કમ્પ્યૂટર (%s) ની ઓળખ અજ્ઞાત છે.\n"
+"આ ત્યારે થાય જ્યારે તમે કમ્પ્યૂટરમાં પ્રથમ વખત પ્રવેશ કરો.\n"
+"\n"
+"દૂરસ્થ કમ્પ્યૂટર દ્વારા મોકલવામાં આવેલ ઓળખ %s છે. જો તમે એકદમ ચોક્કસ થવા માંગો કે ચાલુ રાખવાનું સુરક્ષિત છે, તો સિસ્ટમ સંચાલકનો સંપર્ક કરો."
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "લોગીન સંવાદ કાઢી નંખાયેલ છે"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr "યજમાન ઓળખ ખાતરી મોકલી શકતા નથી"
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+msgid "Protocol error"
+msgstr "પ્રોટોકોલ ભૂલ"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "%s પર %s તરીકે sftp"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "%s પર sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr "આધારિત ssh આદેશને શોધવામાં અસમર્થ"
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "નિષ્ફળતા"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "અયોગ્ય જવાબ મળેલ છે"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead માં અયોગ્ય icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "બેકઅપ ફાઇલ બનાવવામાં ભૂલ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "કામચલાઉ ફાઇલ બનાવવામાં અસમર્થ"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "ડિરેક્ટરી ઉપર ડિરેક્ટરીને ખસેડી શકાતી નથી"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s પર %s વહેંચવા માટે પાસવર્ડની જરૂરિયાત છે"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "આંતરિક ભૂલ (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "વિન્ડો માઉન્ટ કરવામાં નિષ્ફળતા"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "સીક પ્રકાર આધારભૂત નથી"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "બેકઅપ ફાઇલ બનાવવામાં નિષ્ફળતા: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ફાઇલને દૂર કરવામાં ભૂલ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ફાઇલને ખસેડવામાં ભૂલ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "લક્ષ્ય ફાઇલને દૂર કરવામાં ભૂલ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "ડિરેક્ટરી ખસેડવાનું પુનરાવર્તિત કરી શકાતુ નથી"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "વિન્ડો હિસ્સાઓ ફાઇલસિસ્ટમ સેવા"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s માટે પાસવર્ડની જરૂરિયાત છે"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s પર વિન્ડો હિસ્સાઓ"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "સર્વર માંથી વહેંચણી યાદી ને મેળવવામાં નિષ્ફળ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "ફાઇલ ને માઉન્ટ કરી શકાય તેવુ નથી"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "નિયમિત ફાઇલ નથી"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "વિન્ડો નેટવર્ક ફાઇલસિસ્ટમ સેવા"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "કચરાપેટી ફોલ્ડર કાઢી શકાશે નહિં"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "કચરાપેટીમાંની વસ્તુઓ સુધારી શકાશે નહિં"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "કચરાપેટી"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "અયોગ્ય બેકએન્ડ પ્રકાર"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "ભૂલ fd ને મોકલી રહ્યા છે: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "બેકએન્ડ દ્દારા Symlinks આધારભૂત નથી"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "અયોગ્ય dbus સંદેશ"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "જૂના ડેઇમોનને બદલો"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "ફ્યુજ ને શરૂ કરો નહિં"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS ડેઇમોન"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS માટે મુખ્ય ડેઇમોન"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "વધારે જાણકારી માટે \"%s --મદદ\" નો પ્રયત્ન કરો"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "સ્પોન થયેલ છોકરા માંથી અયોગ્ય દલીલો"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "આપોઆપ માઉન્ટમાં નિષ્ફળતા: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "સ્પષ્ટ થયેલ જગ્યા માઉન્ટ થયેલ નથી"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "સ્પષ્ટ થયેલ જગ્યા આધારભૂત નથી"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "જગ્યા પહેલેથી જ માઉન્ટ થયેલ છે"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "સ્થાન માઉન્ટ કરી શકાય તેવું નથી"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ખાલી CD-ROM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ખાલી CD-R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ખાલી CD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ખાલી DVD-ROM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ખાલી DVD-RAM ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ખાલી DVD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ખાલી DVD+R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ખાલી DVD+RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ખાલી DVD+R DL ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ખાલી Blu-Ray ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ખાલી Blu-Ray R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ખાલી Blu-Ray RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ખાલી HD DVD ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ખાલી HD DVD-R ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ખાલી HD DVD-RW ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ખાલી MO Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "ડિસ્ક"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ખાલી ડિસ્ક"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ડ્રાઇવ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ફ્લોપી ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "સોફ્ટવેર RAID ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "ટેપ ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "માસ સંગ્રહ ડ્રાઇવ"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "મીડિયાને કાઢી નાખવામાં નિષ્ફળતા, મીડિયા પર એક અથવા વધારે વોલ્યુમો વ્યસ્ત છે."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "મિશ્ર ઓડિયો/માહિતી ડિસ્ક"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s મીડિયા"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s એન્ક્રિપ્ટ થયેલ માહિતી"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ફાઇલ ખોલવામાં ભૂલ: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout ને લખવામાં ભૂલ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: વાચવામાં ભૂલ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:બંધ કરવામાં ભૂલ: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - LOCATIONS ને પ્રમાણભૂત આઉટપુટ પર ભેગા કરે છે."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr "ફાઈલોને સ્થાનોએ ભેગી કરો અને પ્રમાણભૂત આઉટપુટમાં છાપો. પારંપરિક cat ઉપયોગીતાની જેમ જ કામ કરે છે, પરંતુ gvfs સ્થાનને સ્થાનિક ફાઈલોની જગ્યાએ વાપરી રહ્યા છીએ: ઉદાહરણ તરીકે તમે ભેગું કરવા માટે smb://server/resource/file.txt ને સ્થાન તરીકે લખી શકો છો."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "નોંધ: ખાલી cat માંથી pipe કરો જો તમને તેમાં -n, -T અથવા અન્ય જેવા બંધારણીય વિકલ્પોની જરૂર હોય."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ગેરહાજર જગ્યાઓ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: જગ્યા ખોલવામાં ભૂલ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: કાર્યક્રમ લોન્ચ કરવામાં ભૂલ: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - FILES ને રજીસ્ટર થયેલ કાર્યક્રમ સાથે ખોલે છે."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "ફાઈલનો પ્રકાર સંભાળવા માટે રજીસ્ટર થયેલ મૂળભૂત કાર્યક્રમ સાથે ફાઈલ(ઓ) ખોલે છે."
+
diff --git a/trunk/po/he.po b/trunk/po/he.po
new file mode 100644
index 00000000..c11bdd4b
--- /dev/null
+++ b/trunk/po/he.po
@@ -0,0 +1,1674 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Yair Hershkovitz, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 1\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
+"product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-27 15:51+0000\n"
+"PO-Revision-Date: 2008-08-26 16:28+0200\n"
+"Last-Translator: Mark Krapivner <mark125@gmail.com>\n"
+"Language-Team: he\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operation not supported, files on different mounts"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Invalid return value from get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Invalid return value from query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Couldn't get stream file descriptor"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Invalid return value from open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Didn't get stream file descriptor"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Invalid return value from call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Invalid return value from get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Could not find enclosing mount"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Invalid filename %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Invalid return value from query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Invalid return value from monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Invalid return value from monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:628
+#: ../client/gdaemonfileinputstream.c:781
+#: ../client/gdaemonfileinputstream.c:899
+#: ../client/gdaemonfileinputstream.c:1147
+#: ../client/gdaemonfileinputstream.c:1389
+#: ../client/gdaemonfileoutputstream.c:504
+#: ../client/gdaemonfileoutputstream.c:679
+#: ../client/gdaemonfileoutputstream.c:871
+#: ../client/gdaemonfileoutputstream.c:1050
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+msgid "Operation was cancelled"
+msgstr "הפעולה בוטלה"
+
+#: ../client/gdaemonfileinputstream.c:525
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1680
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:448
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1232
+#: ../client/gdaemonfileoutputstream.c:1242
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Error in stream protocol: %s"
+
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1242
+msgid "End of stream"
+msgstr "End of stream"
+
+#: ../client/gdaemonfileinputstream.c:1328
+#: ../client/gdaemonfileoutputstream.c:979
+msgid "Seek not supported on stream"
+msgstr "Seek not supported on stream"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Error while getting mount info: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Error connecting to daemon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Invalid return value from open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Error creating socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Error connecting to socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Invalid file info format"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Invalid attribute info list content"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Error initializing Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Error creating Avahi resolver: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Malformed dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Can't handle version %d of GVfsIcon encoding"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Malformed input data for GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Error connecting to D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s Filesystem Service"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Error: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Usage: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Usage: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "No mount type specified"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "mountpoint for %s already running"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "error starting mount daemon"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "/ ב-%s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "לא צויין שם מארח"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "קובץ לא קיים"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "הקובץ אינו ספרייה"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "צרוב"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "לא ניתן ליצור ספרייה זמנית"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "ספרייה לא ריקה"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "יוצר CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "קובץ קיים"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "הפעולה לא נתמכת על ידי המנוע"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "קובץ היעד קיים"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "לא נתמך"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Cannot connect to the system bus"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Cannot create libhal context"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Cannot initialize libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "לא צויין כונן"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "הכונן %s לא נימצא"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "הכונן %s אינו מכיל קבצי שמע"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "חיבור cdda על %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "תקליטור שמע"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "מערכת הקבצים עסוקה: קובץ אחד פתוח"
+msgstr[1] "מערכת הקבצים עסוקה: %d קבצים פתוחים"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "אין את קובץ %s על הכונן %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "אין כזה קובץ"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "הקובץ לא קיים או שאינו מסילת שמע"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "שירות מערכת קבצי תקליטורי שמע"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "מחשב"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "מערכת קבצים"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "לא ניתן לפתוח ספרייה"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "לא ניתן לפתוח קובץ הניתן לחיבור"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "שגיאה פנימית: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "לא ניתן לחבר את הקובץ"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "אין מדיה בכונן"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "לא קובץ הניתן לחיבור"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "לא ניתן לנתק את הקובץ"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "לא ניתן להוציא את הקובץ"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "שגיאת HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Could not parse response"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Empty response"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Unexpected reply from server"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Response invalid"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "שיתוף WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "הכנס סיסמה עבור %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "נא להכניס את סיסמת המתווך"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "‏WebDAV ב-%s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "לא ניתן ליצור בקשה"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "קובת היעד כבר קיים"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "יצירץ קובץ גיבוי נכשלה"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "רשת מקומית"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "לא ניתן לנטר את הקובץ או הספרייה."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "רשת"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "חשבונות לא נתמכים"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "המארח סגר את החיבור"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "חיבור המידע נסגר"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "הפעולה בוטלה"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "לא נשאר מקום בשרת"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "פעולה לא נתמכת"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "ההרשאה נדחתה"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "סוג הדף לא ידוע"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "שם קובץ לא תקין"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "broken transmission"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "לא ניתן להתחבר למארח"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr ""
+"הכנס סיסמה עבור ftp כ־%s ב־%s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "הכנס סיסמה עבור ftp ב-%s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp ב-%s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+"‏sftp כ־%s ב־%s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "הקובץ הוא ספרייה"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "גיבויים עדיין לא נתמכים"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "filename too long"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "שם קובץ היעד שגוי"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "‏%s: ‏%d: התיקייה או הקובץ כבר קיימים"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "‏%s: ‏%d: אין כזה קובץ או תיקייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "‏%s: ‏%d: שם קובץ לא תקין"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "‏%s: ‏%d: לא נתמך"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "מצלמה דיגיטלית (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "מצלמה של %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "נגן שמע של %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "מצלמה"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "נגן שמע"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "לא צויין התקן"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "לא ניתן ליצור הקשר gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "שגיאה ביצירת מצלמה"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "שגיאה בטעינת נתוני ההתקן"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "שגיאה בחיפוש נתוני ההתקן"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "שגיאה בקבלת נתוני ההתקן"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "שגיאה בהגדרת שער התקשורת של המצלמה"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "שגיאה באתחול המצלמה"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "חיבור gphoto2 על %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "לא צויינה מצלמה"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "שגיאה ביצירת אובייקט קובץ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "שגיאה בקבלת קובץ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "שגיאה בקבלת נתונים מהקובץ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, fuzzy, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Error in stream protocol: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "לא ספרייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "נכשל בקבלת רשימת תיקיות"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "נכשל בקבלת רשימת קבצים"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "שגיאה ביצירת ספרייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "השם כבר קיים"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "השם החדש ארוך מדי"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "שגיאה בשינוי שם ספרייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "שגיאה בשינוי שם קובץ"
+
+# c-format
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "הספרייה '%s' אינה ריקה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "שגיאה במחיקת ספרייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "שגיאה במחיקת קובץ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "לא ניתן לכתוב לספרייה"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "לא ניתן להקצות קובץ חדש אליו יש להוסיף"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "לא ניתן לקרוא את הקובץ אליו יש להוסיף"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "לא ניתן לקבל נתונים עבור הקובץ אליו יש להוסיף"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "שגיאה בכתיבת קובץ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "לא נתמך (לא אותה ספרייה)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "שגיאת לקוח HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (קידוד לא תקין)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "הודעות ספרייה לא נתמכות"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "רשת Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "מנטר מיקום הרשת"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s ב-%s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "החיבור להתקן אבד"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "ההתקן דורש עדכון תוכנה"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "תוכנית ה-ssh הסתיימה באופן בלתי צפוי"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "שם המארח לא ידוע"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "אין נתיב אל המארח"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "החיבור נדחה על ידי השרת"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "אימות מפתח המארח נכשל"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "לא ניתן להריץ את התוכנית ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "לא ניתן להריץ את התוכנית ssh: ‏%s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:857
+msgid "Enter password"
+msgstr "הכנס סיסמה"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "לא ניתן לשלוח את הסיסמה"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "התחבר בכל זאת"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Cancel Login"
+msgstr "ביטול התחברות"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "תיבת הדו-שיח של התחברות בוטלה"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+msgid "Protocol error"
+msgstr "שגיאת פרוטוקול"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+msgid "sftp for %s on %s"
+msgstr ""
+"‏sftp כ־%s ב-%s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "‏sftp ב-%s"
+
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "כישלון"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "התקבלה תגובה שגויה"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "שגיאה ביצירת קובץ גיבוי: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "לא ניתן לייצר קובץ זמני"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "סיסמה נדרשת עבור השיתוף %s על %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "שגיאה פנימית (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "נכשל בחיבור שיתוף Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "יצירת קובץ גיבוי נכשלה: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "שגיאה במחיקת קובץ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "שגיאה בהעברת קובץ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "שגיאה בהסרת קובץ המטרה: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "שרות מערכת קבצי שיתוף Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "נדרשת סיסמה עבור %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "שיתוף Windows ב-%s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "לא ניתן לחבר את הקובץ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "לא קובץ רגיל"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "שירות מערכת קבצי רשת Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "לא ניתן למחוק את תיקיית האשפה"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "לא ניתן לשנות פריטים באשפה"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "אשפה"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "סוג מנוע שגוי"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "שגיאה בשליחת מתאר קובץ: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "קישורים סימבוליים לא נתמכים על ידי המנוע"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Invalid dbus message"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Replace old daemon."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Don't start fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Daemon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Main daemon for GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Try \"%s --help\" for more information."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "חיבור אוטומטי נכשל: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "המיקום שצויין אינו מחובר"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "המיקום שצויין אינו נתמך"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "המיקום כבר מחובר"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "המיקום אינו מחובר"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "תקליטור CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "תקליטור CD-ROM ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "תקליטור CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "תקליטור CD-R ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "תקליטור CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "תקליטור CD-RW ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "תקליטור DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "תקליטור DVD-ROM ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "תקליטור DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "תקליטור DVD-RAM ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "תקליטור DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "תקליטור DVD-RW ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "תקליטור DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "תקליטור DVD+R ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "תקליטור DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "תקליטור DVD+RW ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "תקליטור DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "תקליטור DVD+R DL ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "תקליטור Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "תקליטור Blu-Ray ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "תקליטור Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "תקליטור Blu-Ray R ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "תקליטור Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "תקליטור Blu-Ray RW ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "תקליטור HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "תקליטור HD DVD ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "תקליטור HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "תקליטור HD DVD-R ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "תקליטור HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "תקליטור HD DVD-RW ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "תקליטור MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "תקליטוק MO ריק"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "תקליטור"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "תקליטורכ ריק"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "כונן ‎%s/‏%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "כונן %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "כונן תקליטונים"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "כונן RAID בתוכנה"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "כונן USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "כונן ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "כונן SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "כונן FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "כונן CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "כונן MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "כונן SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "כונן SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "כונן Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "כונן Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "כונן אצבע"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "נכשל בהוצאת המדיה; כרך אחד או יותר על המדיה עסוקים."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "‏‎%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "‏‎%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "‏‎%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "תקליטור שמע/נתונים משותף"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "מדיה %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "מידע מוצפן %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: error opening file: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, error writing to stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: error reading: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:error closing: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - concatenate LOCATIONS to standard output."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: missing locations"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: error opening location: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: error launching application: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - open FILES with registered application."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "The query info operation is not supported"
+
+#~ msgid "Query info not supported on stream"
+#~ msgstr "Query info not supported on stream"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "לא ניתן למחוק ת האשפה"
+
+#, fuzzy
+#~ msgid "Can't pull trash"
+#~ msgstr "לא ניתן למחוק ת האשפה"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "‏%s (באשפה)"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#, fuzzy
+#~ msgid "Error creating port info list"
+#~ msgstr "Error creating socket: %s"
+
+#, fuzzy
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "Error while getting mount info: %s"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "מערכת הקבצים עסוקה: %d קבצים פתוחים"
+
+#~ msgid "Error listing folders"
+#~ msgstr "שגיאה ברישום תיקיות"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "שגיאה ברישום הקבצים שבתיקייה"
+
+#~ msgid "File unavailable"
+#~ msgstr "קובץ לא זמין"
+
+#~ msgid "CD Burner"
+#~ msgstr "צורב CD"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "דיסק אודיו ב-%s"
+
+#~ msgid "The file does not exist"
+#~ msgstr "הקובץ לא קיים"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "מדיה ‎%.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "מדיה ‎%.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "מדיה ‎%1.f GB"
diff --git a/trunk/po/hi.po b/trunk/po/hi.po
new file mode 100644
index 00000000..f6036abd
--- /dev/null
+++ b/trunk/po/hi.po
@@ -0,0 +1,1348 @@
+# translation of gvfs.HEAD.po to Hindi
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Rajesh Ranjan <rranjan@redhat.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-04 04:07+0000\n"
+"PO-Revision-Date: 2008-03-04 16:18+0530\n"
+"Last-Translator: Rajesh Ranjan <rranjan@redhat.com>\n"
+"Language-Team: Hindi <hindi.sf.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n\n\n"
+"\n"
+"\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:464 ../client/gdaemonfile.c:1867
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:758
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:865
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:897 ../client/gdaemonfile.c:967
+#: ../client/gdaemonfile.c:1026 ../client/gdaemonfile.c:1085
+#: ../client/gdaemonfile.c:1147
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:977 ../client/gdaemonfile.c:1036
+#: ../client/gdaemonfile.c:1095 ../client/gdaemonfile.c:1157
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1209 ../client/gdaemonfile.c:1226
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1505
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1549
+msgid "Could not find enclosing mount"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1579
+#, c-format
+msgid "Invalid filename %s"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1621
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2012
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2061
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:451
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1304
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:403
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../client/gdaemonfileoutputstream.c:1062
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1062
+msgid "End of stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:519
+#: ../client/gdaemonfileinputstream.c:676
+#: ../client/gdaemonfileinputstream.c:785
+#: ../client/gdaemonfileinputstream.c:1036
+#: ../client/gdaemonfileoutputstream.c:460
+#: ../client/gdaemonfileoutputstream.c:639
+#: ../client/gdaemonfileoutputstream.c:835 ../daemon/gvfsbackendobexftp.c:753
+#: ../daemon/gvfsbackendobexftp.c:774 ../daemon/gvfsbackendobexftp.c:893
+#: ../daemon/gvfsbackendobexftp.c:1030 ../daemon/gvfsbackendobexftp.c:1094
+#: ../daemon/gvfsbackendobexftp.c:1220 ../daemon/gvfsbackendobexftp.c:1247
+#: ../daemon/gvfsbackendobexftp.c:1306 ../daemon/gvfsbackendobexftp.c:1328
+#: ../daemon/gvfsbackendobexftp.c:1388 ../daemon/gvfsbackendobexftp.c:1407
+#: ../daemon/gvfsbackendsmb.c:1014 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:297
+msgid "Operation was cancelled"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1211
+#: ../client/gdaemonfileoutputstream.c:946
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1241
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:712
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:559 ../client/gvfsdaemondbus.c:946
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:127
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:165
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr ""
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "त्रुटि: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:347
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:377
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:406 ../daemon/gvfsbackendburn.c:417
+#: ../daemon/gvfsbackendburn.c:452 ../daemon/gvfsbackendburn.c:673
+#: ../daemon/gvfsbackendburn.c:720 ../daemon/gvfsbackendburn.c:746
+#: ../daemon/gvfsbackendburn.c:784
+msgid "No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:426 ../daemon/gvfsbackenddav.c:1748
+msgid "Directory not empty"
+msgstr "डिरेक्ट्री रिक्त नहीं है"
+
+#: ../daemon/gvfsbackendburn.c:460 ../daemon/gvfsbackendburn.c:898
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:652
+msgid "CD/DVD Creator"
+msgstr "CD/DVD सर्जक"
+
+#: ../daemon/gvfsbackendburn.c:681 ../daemon/gvfsbackendcomputer.c:652
+#: ../daemon/gvfsbackenddnssd.c:393 ../daemon/gvfsbackendftp.c:766
+#: ../daemon/gvfsbackendnetwork.c:637
+#, c-format
+msgid "The file is not a directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:756 ../daemon/gvfsbackendburn.c:792
+#: ../daemon/gvfsbackendburn.c:918
+msgid "File exists"
+msgstr "फ़ाइल मौज़ूद है"
+
+#: ../daemon/gvfsbackendburn.c:846
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:869
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:878
+msgid "Target file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:885
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:944
+msgid "Not supported"
+msgstr "समर्थित नहीं"
+
+#: ../daemon/gvfsbackendcdda.c:264 ../daemon/gvfsbackendcdda.c:335
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:279
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:289
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:297
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:298 ../daemon/gvfsbackendcdda.c:802
+#: ../hal/ghalmount.c:488 ../hal/ghalvolume.c:286 ../hal/ghalvolume.c:307
+#, c-format
+msgid "Audio Disc"
+msgstr "ऑडियो डिस्क"
+
+#: ../daemon/gvfsbackendcdda.c:359
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ../daemon/gvfsbackendcdda.c:549
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr ""
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:658
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:721
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:818 ../daemon/gvfsbackendgphoto2.c:1695
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:825 ../daemon/gvfsbackendcomputer.c:573
+#: ../daemon/gvfsbackenddnssd.c:345 ../daemon/gvfsbackendftp.c:1825
+#: ../daemon/gvfsbackendnetwork.c:590 ../daemon/gvfsbackendsmbbrowse.c:799
+#: ../daemon/gvfsbackendsmbbrowse.c:866 ../daemon/gvfsbackendsmbbrowse.c:1037
+#: ../daemon/gvfsbackendsmbbrowse.c:1111
+#, c-format
+msgid "File doesn't exist"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:832
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:938
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:180 ../daemon/gvfsbackendcomputer.c:694
+msgid "Computer"
+msgstr "कम्प्यूटर"
+
+#: ../daemon/gvfsbackendcomputer.c:467
+msgid "Filesystem"
+msgstr "फ़ाइलसिस्टम"
+
+#: ../daemon/gvfsbackendcomputer.c:591 ../daemon/gvfsbackendgphoto2.c:1687
+#: ../daemon/gvfsbackendobexftp.c:739 ../daemon/gvfsbackendtrash.c:637
+msgid "Can't open directory"
+msgstr "डैरक्टरी नहीं खोल सकते है"
+
+#: ../daemon/gvfsbackendcomputer.c:595 ../daemon/gvfsbackendcomputer.c:733
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:781
+#, c-format
+msgid "Internal error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:813 ../daemon/gvfsbackendcomputer.c:927
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:822
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:879 ../daemon/gvfsbackendcomputer.c:970
+#: ../daemon/gvfsbackendcomputer.c:1070
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:985
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1101
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:271 ../daemon/gvfsbackenddav.c:1243
+#: ../daemon/gvfsbackendhttp.c:220
+#, c-format
+msgid "HTTP Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:287
+msgid "Could not parse response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:296
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:303
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:903 ../daemon/gvfsbackenddav.c:1362
+#, c-format
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1046
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1048
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s के लिये शब्दकूट डालें"
+
+#: ../daemon/gvfsbackenddav.c:1051
+msgid "Please enter proxy password"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1160 ../daemon/gvfsbackendhttp.c:273
+#: ../daemon/gvfsbackendobexftp.c:592 ../daemon/gvfsbackendobexftp.c:603
+#: ../daemon/gvfsbackendsmb.c:594
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1247 ../daemon/gvfsbackenddav.c:1251
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1318 ../daemon/gvfsbackenddav.c:1391
+msgid "Could not create request"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1457 ../daemon/gvfsbackenddav.c:1706
+#: ../daemon/gvfsbackendsmb.c:1726
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackendsftp.c:2689
+#: ../daemon/gvfsbackendsmb.c:982
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1558 ../daemon/gvfsbackendsmb.c:1020
+#: ../daemon/gvfsbackendsmb.c:1743
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "नेटवर्क"
+
+#: ../daemon/gvfsbackendftp.c:188
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:192
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:196
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:200
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:206
+msgid "File unavailable"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:210
+msgid "Operation failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:215
+msgid "No space left on server"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:223
+msgid "Operation unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:227 ../daemon/gvfsbackendsftp.c:261
+msgid "Permission denied"
+msgstr "अनुमति निषेधित"
+
+#: ../daemon/gvfsbackendftp.c:231
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:235 ../daemon/gvfsbackendftp.c:1900
+#, c-format
+msgid "Invalid filename"
+msgstr "अवैध फाइलनाम"
+
+#: ../daemon/gvfsbackendftp.c:239 ../daemon/gvfsbackendftp.c:313
+#: ../daemon/gvfsbackendftp.c:342 ../daemon/gvfsbackendftp.c:361
+#: ../daemon/gvfsbackendftp.c:374 ../daemon/gvfsbackendftp.c:671
+#, c-format
+msgid "Invalid reply"
+msgstr "अवैध उत्तर"
+
+#: ../daemon/gvfsbackendftp.c:481
+#, c-format
+msgid "broken transmission"
+msgstr "टूटा प्रेषण"
+
+#: ../daemon/gvfsbackendftp.c:574 ../daemon/gvfsbackendftp.c:690
+#, c-format
+msgid "Could not connect to host"
+msgstr "मेजबान में जोड़ नहीं सका"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:964
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:983 ../daemon/gvfsbackendsftp.c:834
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1035
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp %s पर"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1041
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1075 ../daemon/gvfsbackendsftp.c:1411
+msgid "No hostname specified"
+msgstr "कोई मेजबाननाम निर्दिष्ट नहीं"
+
+#: ../daemon/gvfsbackendftp.c:1281 ../daemon/gvfsbackendftp.c:1991
+msgid "backups not supported yet"
+msgstr "backups अबतक समर्थित नहीं"
+
+#: ../daemon/gvfsbackendftp.c:1496 ../daemon/gvfsbackendftp.c:1696
+#, c-format
+msgid "filename too long"
+msgstr "फाइलनाम बहुत लंबा है"
+
+#: ../daemon/gvfsbackendftp.c:2010
+#, c-format
+msgid "Invalid destination filename"
+msgstr "अवैध गंतव्य फाइलनाम"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:697
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "डिजिटल कैमरा (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:843 ../hal/ghalvolume.c:390
+#, c-format
+msgid "%s Camera"
+msgstr "%s कैमरा"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:846 ../hal/ghalvolume.c:385
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ऑडियो प्लेयर"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../hal/ghalvolume.c:402
+msgid "Camera"
+msgstr "कैमरा"
+
+#: ../daemon/gvfsbackendgphoto2.c:857 ../hal/ghalvolume.c:398
+msgid "Audio Player"
+msgstr "श्रव्य चालक"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1539
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 %s पर माउंट"
+
+#: ../daemon/gvfsbackendhttp.c:216
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP क्लाइंट त्रुटि: %s"
+
+#: ../daemon/gvfsbackendhttp.c:534 ../daemon/gvfsbackendsftp.c:1751
+#: ../daemon/gvfsbackendsmb.c:1229 ../daemon/gvfsbackendtrash.c:962
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (अवैध एनकोडिंग)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "निर्देशिका अधिसूचना अबतक समर्थित नहीं"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:694
+msgid "Windows Network"
+msgstr "विंडोज़ नेटवर्क"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "स्थानीय संजाल"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "संजाल स्थान मानिटर"
+
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:431 ../daemon/gvfsbackendsmb.c:513
+#: ../daemon/gvfsbackendsmb.c:1222
+#, c-format
+msgid "%s on %s"
+msgstr "%s %s पर"
+
+#: ../daemon/gvfsbackendsftp.c:253
+msgid "ssh program unexpectedly exited"
+msgstr "ssh प्रोग्राम अप्रत्याशित रूप से बाहर निकल गया"
+
+#: ../daemon/gvfsbackendsftp.c:268
+msgid "Hostname not known"
+msgstr "मेजबाननाम नहीं ज्ञात"
+
+#: ../daemon/gvfsbackendsftp.c:275
+msgid "No route to host"
+msgstr "मेजबान में कोई रूट नहीं"
+
+#: ../daemon/gvfsbackendsftp.c:282
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:289
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:372
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:388
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:491 ../daemon/gvfsbackendsftp.c:743
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:819
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:821
+msgid "Enter password"
+msgstr "शब्दकूट दाखिल करें"
+
+#: ../daemon/gvfsbackendsftp.c:881
+msgid "Can't send password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:889
+msgid "Log In Anyway"
+msgstr "किसी तरह लॉगिन करें"
+
+#: ../daemon/gvfsbackendsftp.c:889
+msgid "Cancel Login"
+msgstr "लॉगिन रद्द करें"
+
+#: ../daemon/gvfsbackendsftp.c:899
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:919
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1330 ../daemon/gvfsbackendsftp.c:1353
+msgid "Protocol error"
+msgstr "प्रोटोकॉल त्रुटि"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1377
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp %s पर"
+
+#: ../daemon/gvfsbackendsftp.c:1401
+msgid "Unable to find supported ssh command"
+msgstr ""
+
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1763
+#, c-format
+msgid "/ on %s"
+msgstr "/ on %s"
+
+#: ../daemon/gvfsbackendsftp.c:1827
+msgid "File is directory"
+msgstr "फाइल निर्देशिका है"
+
+#: ../daemon/gvfsbackendsftp.c:1836
+msgid "Failure"
+msgstr "विफलता"
+
+#: ../daemon/gvfsbackendsftp.c:1901 ../daemon/gvfsbackendsftp.c:1963
+#: ../daemon/gvfsbackendsftp.c:1974 ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2151
+#: ../daemon/gvfsbackendsftp.c:2199 ../daemon/gvfsbackendsftp.c:2278
+#: ../daemon/gvfsbackendsftp.c:2389 ../daemon/gvfsbackendsftp.c:2430
+#: ../daemon/gvfsbackendsftp.c:2482 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2573 ../daemon/gvfsbackendsftp.c:2727
+#: ../daemon/gvfsbackendsftp.c:2753 ../daemon/gvfsbackendsftp.c:2810
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:3149
+#: ../daemon/gvfsbackendsftp.c:3278 ../daemon/gvfsbackendsftp.c:3311
+#: ../daemon/gvfsbackendsftp.c:3412 ../daemon/gvfsbackendsftp.c:3453
+#: ../daemon/gvfsbackendsftp.c:3509 ../daemon/gvfsbackendsftp.c:3545
+#: ../daemon/gvfsbackendsftp.c:3579 ../daemon/gvfsbackendsftp.c:3594
+#: ../daemon/gvfsbackendsftp.c:3613
+msgid "Invalid reply received"
+msgstr "अवैध उत्तर प्राप्त"
+
+#: ../daemon/gvfsbackendsftp.c:2220
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "बैकअप फाइल बनाने में त्रुटि: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2635
+msgid "Unable to create temporary file"
+msgstr "अस्थायी फाइल बनाने में असमर्थ"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:214
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:465 ../daemon/gvfsbackendsmb.c:505
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "आंतरिक त्रुटि (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:560
+msgid "Failed to mount Windows share"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:685 ../daemon/gvfsbackendsmb.c:1116
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1170
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1627
+#, c-format
+msgid "Error deleting file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1691
+#, c-format
+msgid "Error moving file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1715
+msgid "Can't move directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1763
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1787
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1850
+msgid "Windows Shares Filesystem Service"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:702
+#, c-format
+msgid "Windows shares on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:794 ../daemon/gvfsbackendsmbbrowse.c:840
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:862
+msgid "Not a regular file"
+msgstr "एक सामान्य फाइल नहीं"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1107
+msgid "Not a directory"
+msgstr "डिरेक्ट्री नहीं है"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1219
+msgid "Windows Network Filesystem Service"
+msgstr ""
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:600 ../daemon/gvfsbackendtrash.c:1190
+msgid "Trash"
+msgstr "रद्दी"
+
+#: ../daemon/gvfsbackendtrash.c:972
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (in trash)"
+
+#: ../daemon/gvfsbackendtrash.c:1291
+msgid "Can't delete trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1638 ../daemon/gvfsbackendtrash.c:1713
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr ""
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr ""
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:119
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:169 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr ""
+
+#: ../daemon/main.c:47
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:48
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:60
+msgid "GVFS Daemon"
+msgstr "GVFS डेमान"
+
+#: ../daemon/main.c:63
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:74
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:76 ../programs/gvfs-cat.c:167 ../programs/gvfs-open.c:135
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+
+#: ../daemon/mount.c:432
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:731
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:776
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:781
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:944
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:952
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../hal/ghaldrive.c:142
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../hal/ghaldrive.c:144
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../hal/ghaldrive.c:146
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../hal/ghaldrive.c:150
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../hal/ghaldrive.c:152
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../hal/ghaldrive.c:154
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../hal/ghaldrive.c:156
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../hal/ghaldrive.c:158
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../hal/ghaldrive.c:160
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../hal/ghaldrive.c:163
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../hal/ghaldrive.c:166
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../hal/ghaldrive.c:168
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../hal/ghaldrive.c:170
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../hal/ghaldrive.c:172
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../hal/ghaldrive.c:174
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../hal/ghaldrive.c:176
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../hal/ghaldrive.c:178
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../hal/ghaldrive.c:184
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s चालन"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../hal/ghaldrive.c:190
+#, c-format
+msgid "%s Drive"
+msgstr "%s चालन"
+
+#: ../hal/ghaldrive.c:194
+msgid "Floppy Drive"
+msgstr "फ्लॉपी ड्राइव"
+
+#: ../hal/ghaldrive.c:200
+msgid "Software RAID Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:202
+msgid "USB Drive"
+msgstr "USB चालन"
+
+#: ../hal/ghaldrive.c:204
+msgid "ATA Drive"
+msgstr "ATA ड्राइव"
+
+#: ../hal/ghaldrive.c:206
+msgid "SCSI Drive"
+msgstr "SCSI ड्राइव"
+
+#: ../hal/ghaldrive.c:208
+msgid "FireWire Drive"
+msgstr "FireWire ड्राइव"
+
+#: ../hal/ghaldrive.c:212
+msgid "Tape Drive"
+msgstr "Tape ड्राइव"
+
+#: ../hal/ghaldrive.c:214
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ड्राइव"
+
+#: ../hal/ghaldrive.c:216
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ड्राइव"
+
+#: ../hal/ghaldrive.c:218
+msgid "SmartMedia Drive"
+msgstr "Smartमीडिया ड्राइव"
+
+#: ../hal/ghaldrive.c:220
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ड्राइव"
+
+#: ../hal/ghaldrive.c:222
+msgid "Zip Drive"
+msgstr "ज़िप ड्राइव"
+
+#: ../hal/ghaldrive.c:224
+msgid "Jaz Drive"
+msgstr "ज़िप ड्राइव"
+
+#: ../hal/ghaldrive.c:226
+msgid "Thumb Drive"
+msgstr "Thumb ड्राइव"
+
+#: ../hal/ghaldrive.c:229
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:653
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../hal/ghalmount.c:147 ../hal/ghalvolume.c:139
+msgid "CD-ROM Disc"
+msgstr "सीडी-रोम डिस्क"
+
+#: ../hal/ghalmount.c:147 ../hal/ghalvolume.c:139
+msgid "Blank CD-ROM Disc"
+msgstr "खाली CD-ROM डिस्क"
+
+#: ../hal/ghalmount.c:148 ../hal/ghalvolume.c:140
+msgid "CD-R Disc"
+msgstr "CD-R डिस्क"
+
+#: ../hal/ghalmount.c:148 ../hal/ghalvolume.c:140
+msgid "Blank CD-R Disc"
+msgstr "खाली CD-R डिस्क"
+
+#: ../hal/ghalmount.c:149 ../hal/ghalvolume.c:141
+msgid "CD-RW Disc"
+msgstr "CD-RW डिस्क"
+
+#: ../hal/ghalmount.c:149 ../hal/ghalvolume.c:141
+msgid "Blank CD-RW Disc"
+msgstr "खाली CD-RW डिस्क"
+
+#: ../hal/ghalmount.c:150 ../hal/ghalmount.c:152 ../hal/ghalvolume.c:142
+#: ../hal/ghalvolume.c:144
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM डिस्क"
+
+#: ../hal/ghalmount.c:150 ../hal/ghalmount.c:152 ../hal/ghalvolume.c:142
+#: ../hal/ghalvolume.c:144
+msgid "Blank DVD-ROM Disc"
+msgstr "खाली DVD-ROM डिस्क"
+
+#: ../hal/ghalmount.c:151 ../hal/ghalvolume.c:143
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM डिस्क"
+
+#: ../hal/ghalmount.c:151 ../hal/ghalvolume.c:143
+msgid "Blank DVD-RAM Disc"
+msgstr "खाली DVD-RAM डिस्क"
+
+#: ../hal/ghalmount.c:153 ../hal/ghalvolume.c:145
+msgid "DVD-RW Disc"
+msgstr "DVD-RW डिस्क"
+
+#: ../hal/ghalmount.c:153 ../hal/ghalvolume.c:145
+msgid "Blank DVD-RW Disc"
+msgstr "खाली DVD-RW डिस्क"
+
+#: ../hal/ghalmount.c:154 ../hal/ghalvolume.c:146
+msgid "DVD+R Disc"
+msgstr "DVD+R डिस्क"
+
+#: ../hal/ghalmount.c:154 ../hal/ghalvolume.c:146
+msgid "Blank DVD+R Disc"
+msgstr "खाली DVD+R डिस्क"
+
+#: ../hal/ghalmount.c:155 ../hal/ghalvolume.c:147
+msgid "DVD+RW Disc"
+msgstr "DVD+RW डिस्क"
+
+#: ../hal/ghalmount.c:155 ../hal/ghalvolume.c:147
+msgid "Blank DVD+RW Disc"
+msgstr "खाली DVD+RW डिस्क"
+
+#: ../hal/ghalmount.c:156 ../hal/ghalvolume.c:148
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL डिस्क"
+
+#: ../hal/ghalmount.c:156 ../hal/ghalvolume.c:148
+msgid "Blank DVD+R DL Disc"
+msgstr "खाली DVD+R DL डिस्क"
+
+#: ../hal/ghalmount.c:157 ../hal/ghalvolume.c:149
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray डिस्क"
+
+#: ../hal/ghalmount.c:157 ../hal/ghalvolume.c:149
+msgid "Blank Blu-Ray Disc"
+msgstr "खाली Blu-Ray डिस्क"
+
+#: ../hal/ghalmount.c:158 ../hal/ghalvolume.c:150
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R डिस्क"
+
+#: ../hal/ghalmount.c:158 ../hal/ghalvolume.c:150
+msgid "Blank Blu-Ray R Disc"
+msgstr "खाली Blu-Ray R डिस्क"
+
+#: ../hal/ghalmount.c:159 ../hal/ghalvolume.c:151
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW डिस्क"
+
+#: ../hal/ghalmount.c:159 ../hal/ghalvolume.c:151
+msgid "Blank Blu-Ray RW Disc"
+msgstr "खाली Blu-Ray RW डिस्क"
+
+#: ../hal/ghalmount.c:160 ../hal/ghalvolume.c:152
+msgid "HD DVD Disc"
+msgstr "HD DVD डिस्क"
+
+#: ../hal/ghalmount.c:160 ../hal/ghalvolume.c:152
+msgid "Blank HD DVD Disc"
+msgstr "खाली HD DVD डिस्क"
+
+#: ../hal/ghalmount.c:161 ../hal/ghalvolume.c:153
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R डिस्क"
+
+#: ../hal/ghalmount.c:161 ../hal/ghalvolume.c:153
+msgid "Blank HD DVD-R Disc"
+msgstr "खाली HD DVD-R डिस्क"
+
+#: ../hal/ghalmount.c:162 ../hal/ghalvolume.c:154
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW डिस्क"
+
+#: ../hal/ghalmount.c:162 ../hal/ghalvolume.c:154
+msgid "Blank HD DVD-RW Disc"
+msgstr "खाली HD DVD-RW डिस्क"
+
+#: ../hal/ghalmount.c:163 ../hal/ghalvolume.c:155
+msgid "MO Disc"
+msgstr "MO डिस्क"
+
+#: ../hal/ghalmount.c:163 ../hal/ghalvolume.c:155
+msgid "Blank MO Disc"
+msgstr "खाली MO डिस्क"
+
+#: ../hal/ghalmount.c:164 ../hal/ghalvolume.c:156
+msgid "Disc"
+msgstr "डिस्क"
+
+#: ../hal/ghalmount.c:164 ../hal/ghalvolume.c:156
+msgid "Blank Disc"
+msgstr "खाली डिस्क"
+
+#: ../hal/ghalmount.c:349
+#, c-format
+msgid "%.1f kB Media"
+msgstr "%.1f kB मीडिया"
+
+#: ../hal/ghalmount.c:354
+#, c-format
+msgid "%.1f MB Media"
+msgstr "%.1f MB मीडिया"
+
+#: ../hal/ghalmount.c:359
+#, c-format
+msgid "%.1f GB Media"
+msgstr "%.1f GB मीडिया"
+
+#: ../hal/ghalmount.c:486 ../hal/ghalvolume.c:305
+msgid "Mixed Audio/Data Disc"
+msgstr "मिश्रित ऑडियो/आंकड़ा डिस्क"
+
+#: ../hal/ghalvolume.c:190
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../hal/ghalvolume.c:195
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../hal/ghalvolume.c:200
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:293
+#, c-format
+msgid "%s Encrypted Data"
+msgstr ""
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:316
+#, c-format
+msgid "%s Media"
+msgstr "%s मीडिया"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:59
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:82
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:94
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:112
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-cat.c:138
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:143
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:150
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:165 ../programs/gvfs-open.c:133
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:58
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:85
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:115
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:119
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
diff --git a/trunk/po/hu.po b/trunk/po/hu.po
new file mode 100644
index 00000000..e0a21a81
--- /dev/null
+++ b/trunk/po/hu.po
@@ -0,0 +1,1632 @@
+# Hungarian translation of gvfs
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+#
+# Gabor Kelemen <kelemeng@gnome.hu>, 2008, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs head\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-04 19:03+0000\n"
+"PO-Revision-Date: 2009-02-08 18:39+0100\n"
+"Last-Translator: Gabor Kelemen <kelemeng@gnome.hu>\n"
+"Language-Team: Hungarian <gnome@fsf.hu>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "A művelet nem támogatott, a fájlok eltérő csatolásokon vannak"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "A get_info visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "A query_info visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Az adatfolyamfájl leírója nem kérhető le"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Az open visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Az adatfolyamfájl-leíró lekérése meghiúsult"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "A hívás visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "A get_filesystem_info visszatérési értéke érvénytelen"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nem található befoglaló csatolási objektum"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Érvénytelen fájlnév: %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "A query_filesystem_info visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "A monitor_dir visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "A monitor_file visszatérési értéke érvénytelen"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "A művelet megszakítva"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Hiba az adatfolyam-protokollban: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Vége az adatfolyamnak"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Az adatfolyam nem támogatja a pozicionálást"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Az információk lekérése művelet nem támogatott"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Az információk lekérését az adatfolyam nem támogatja"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Hiba a csatolási információk lekérésekor: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Hiba a démonhoz csatlakozáskor: %s"
+
+#: ../client/gvfsiconloadable.c:145
+#| msgid "Invalid return value from get_info"
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Az open_icon_for_read visszatérési értéke érvénytelen"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Hiba a foglalat létrehozásakor: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Hiba a foglalathoz csatlakozáskor: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Érvénytelen fájlinformáció-formátum"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Érvénytelen attribútuminformáció-lista tartalom"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error initializing camera"
+msgid "Error initializing Avahi: %s"
+msgstr "Hiba az Avahi előkészítésekor: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating socket: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "Hiba az Avahi feloldó létrehozásakor: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Hiba „%s” feloldásakor, szolgáltatás: „%s”, tartomány: „%s”"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr "Hiba „%s” feloldásakor, szolgáltatás: „%s”, tartomány: „%s”. Néhány TXT rekord hiányzik. A szükséges kulcsok: „%s”."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Időtúllépés „%s” feloldásakor, szolgáltatás: „%s”, tartomány: „%s”"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Rosszul formált dns-sd encoded_triple „%s”"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Nem kezelhető a GVfsIcon kódolás %d. verziója"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Rosszul formált adatok a GVfsIconhoz"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Hiba a D-Bushoz csatlakozáskor: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s fájlrendszer-szolgáltatás"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Hiba: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Használat: %s --spawner dbus-azonosító objektum_útvonal"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Használat: %s kulcs=érték kulcs=érték…"
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Nincs megadva csatolástípus"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "A(z) %s csatolási pontja már fut"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "hiba a csatolási démon indításakor"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ ezen: %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Nincs megadva gépnév"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Érvénytelen csatolási meghatározás"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:399
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:647
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "A fájl nem létezik"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:446
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:694
+msgid "The file is not a directory"
+msgstr "A fájl nem egy könyvtár"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Írás"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nem lehet ideiglenes könyvtárat létrehozni"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Nincs ilyen fájl vagy könyvtár"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "A könyvtár nem üres"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "A könyvtár nem másolható át könyvtárba"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-készítő"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "A fájl létezik"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "A háttérprogram nem támogatja a műveletet"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Nincs ilyen fájl vagy könyvtár a célútvonalon"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "A könyvtár nem másolható át könyvtárba"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "A célfájl létezik"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "A könyvtár nem másolható rekurzívan"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Nem támogatott"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Nem lehet csatlakozni a rendszerbuszhoz"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Nem hozható létre libhal kontextus"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "A libhal nem készíthető elő"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nincs megadva meghajtó"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "A(z) %s meghajtó nem található"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "A(z) %s meghajtó nem tartalmaz hangfájlokat"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda csatolás a következőn: %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio lemez"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "A fájlrendszer foglalt: %d megnyitott fájl"
+msgstr[1] "A fájlrendszer foglalt: %d megnyitott fájl"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nincs %s nevű fájl a(z) %s meghajtón"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Hiba a „paranoia” programtól a következő meghajtón: %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Hiba az adatfolyamban pozicionálásakor a(z) %s meghajtón"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Nincs ilyen fájl"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "A fájl nem létezik vagy nem egy hangsáv"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Hang CD fájlrendszer-szolgáltatás"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Számítógép"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Fájlrendszer"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "A könyvtár nem nyitható meg"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Nem nyitható meg csatolható fájl"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Belső hiba: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "A fájl nem csatolható"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Nincs adathordozó a meghajtóban"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Nem csatolható fájl"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "A fájl nem választható le"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "A fájl nem adható ki"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP hiba: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "A válasz nem elemezhető"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Üres válasz"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Váratlan válasz a kiszolgálótól"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "A válasz érvénytelen"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV megosztás"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Adja meg %s jelszavát"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Adja meg a proxy jelszót"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Nem WebDAV-képes megosztás"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV a következőn: %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Nem hozható létre kérés"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "A célfájl már létezik"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "A fájlt külső program módosította"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "A mentési fájl létrehozása meghiúsult"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:493 ../daemon/gvfsbackendnetwork.c:394
+msgid "Local Network"
+msgstr "Helyi hálózat"
+
+#: ../daemon/gvfsbackenddnssd.c:737 ../daemon/gvfsbackendnetwork.c:798
+msgid "Can't monitor file or directory."
+msgstr "A fájl vagy könyvtár nem figyelhető meg."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:755
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:756 ../daemon/gvfsbackendnetwork.c:733
+#: ../daemon/gvfsbackendnetwork.c:883 ../daemon/gvfsbackendnetwork.c:884
+msgid "Network"
+msgstr "Hálózat"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "A fiókok nem támogatottak"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "A gép lezárta a kapcsolatot"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Nem nyitható meg az adatkapcsolat. Lehet, hogy a tűzfal akadályozza?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Az adatkapcsolat lezárva"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "A művelet meghiúsult"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Nincs több hely a kiszolgálón"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "A művelet nem támogatott"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Hozzáférés megtagadva"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Az oldaltípus ismeretlen"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Érvénytelen fájlnév"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Érvénytelen válasz"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "sérült átvitel"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Nem lehet csatlakozni a géphez"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+#| msgid "Enter password for ftp on %s"
+msgid "Enter password for ftp as %s on %s"
+msgstr "Adja meg %s:%s FTP jelszavát"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Adja meg %s FTP jelszavát"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "A jelszó megadása megszakítva"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp a következőn: %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp %s néven a következőn: %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "A fájl könyvtár"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "biztonsági másolatok még nem támogatottak"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "a fájlnév túl hosszú"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Érvénytelen célfájlnév"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: A könyvtár vagy fájl létezik"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d Nincs ilyen fájl vagy könyvtár"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Érvénytelen fájlnév"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nem támogatott"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitális fényképezőgép (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s fényképezőgép"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s zenelejátszó"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Fényképezőgép"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Zenelejátszó"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Nincs megadva eszköz"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Nem hozható létre gphoto2 kontextus"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Hiba a fényképezőgép létrehozásakor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Hiba az eszközinformációk létrehozásakor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Hiba az eszközinformációk kikeresésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Hiba az eszközinformációk lekérésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Hiba a fényképezőgép kommunikációs portjának beállításakor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Hiba a fényképezőgép előkészítésekor"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 csatolás a következőn: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Nincs megadva fényképezőgép"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Hiba a fájlobjektum létrehozásakor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Hiba a fájl lekérésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Hiba a fájl adatainak kérésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Rosszul formált ikonazonosító: „%s”"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Hiba az adatfolyamban pozicionálásakor a(z) %s fényképezőgépen"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Nem könyvtár"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "A mappalista lekérése meghiúsult"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "A fájllista lekérése meghiúsult"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Hiba a könyvtár létrehozásakor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "A név már létezik"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "A név túl hosszú"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Hiba a könyvtár átnevezésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Hiba a fájl átnevezésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "A könyvtár („%s”) nem üres"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Hiba a könyvtár törlésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Hiba a fájl törlésekor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "A könyvtár nem írható"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Nem foglalható új fájl a hozzáfűzéshez"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Nem olvasható a fájl a hozzáfűzéshez"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Nem kérhetők le a hozzáfűzési fájl adatai"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Hiba a fájl írása közben"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Nem támogatott (nem ugyanaz a könyvtár)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nem támogatott (a forrás könyvtár, a cél könyvtár)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nem támogatott (a forrás könyvtár, a cél meglévő fájl)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nem támogatott (a forrás fájl, a cél könyvtár)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP klienshiba: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (érvénytelen kódolás)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "A könyvtárértesítés nem támogatott"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows hálózat"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:932
+msgid "Network Location Monitor"
+msgstr "Hálózati helyek figyelése"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s ezen: %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Az USB támogatás hiányzik. Lépjen kapcsolatba a szoftver szállítójával."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "A kapcsolat elveszett az eszközzel"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Az eszköz szoftverfrissítést igényel"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "az ssh program váratlanul kilépett"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "A gépnév ismeretlen"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Nincs útvonal a kiszolgálóhoz"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "A kiszolgáló visszautasította a kapcsolatot"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "A gép kulcsának ellenőrzése meghiúsult"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Az ssh program nem indítható"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Az ssh program nem indítható: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Időtúllépés a bejelentkezéskor"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Adja meg a kulcs jelmondatát"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Adja meg a jelszót"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "A jelszó nem küldhető el"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Bejelentkezés mindenképpen"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Bejelentkezés megszakítása"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"A távoli számítógép (%s) azonossága ismeretlen.\n"
+"Ez akkor fordul elő, ha először jelentkezik be egy számtógépre.\n"
+"\n"
+"A távoli számítógép által küldött azonosság: %s. Ha nem teljesen biztos "
+"abban, hogy biztonságos a folytatás, keresse meg a rendszergazdát."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "A bejelentkezés megszakítva"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "A gép azonossági információi nem küldhetők el"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokollhiba"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+#| msgid "ftp as %s on %s"
+msgid "sftp for %s on %s"
+msgstr "sftp %s néven a következőn: %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp a következőn: %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Nem található támogatott ssh parancs"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Hiba"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Érvénytelen válasz érkezett"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Érvénytelen icon_id (%s) az OpenIconForRead hívásban"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Hiba a mentési fájl létrehozásakor: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Nem lehet ideiglenes fájlt létrehozni"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "A könyvtár nem helyezhető át könyvtárba"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Jelszó szükséges a(z) %2$s gép %1$s megosztásához"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Belső hiba (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "A Windows megosztás csatolása meghiúsult"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Nem támogatott pozicionálástípus"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "A mentési fájl létrehozása meghiúsult: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Hiba a fájl törlésekor: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Hiba a fájl áthelyezésekor: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Hiba a célfájl eltávolításakor: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "A könyvtár nem helyezhető át rekurzívan"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows megosztások fájlrendszer-szolgáltatás"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+#| msgid "Password required for share %s on %s"
+msgid "Password required for %s"
+msgstr "Jelszó szükséges a következőhöz: %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows megosztások ezen: %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "A megosztások listájának lekérése meghiúsult a kiszolgálóról"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "A fájl nem csatolható"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Nem szabályos fájl"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows hálózat fájlrendszer-szolgáltatás"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "A trash mappa nem törölhető"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "A Kuka elemei nem módosíthatók"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Kuka"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Érvénytelen háttérprogram-típus"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Hiba a fájlleíró küldésekor: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "A háttérprogram nem támogatja a szimbolikus linkeket"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Érvénytelen D-Bus üzenet"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "A régi démon helyettesítése."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Ne indítsa a fuse-t."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS démon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "A GVFS elsődleges démona"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "További információkért adja ki a következő parancsot: „%s --help”."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Az elindított gyermek érvénytelen argumentumokat adott"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Az automatikus csatolás meghiúsult: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "A megadott hely nincs csatolva"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "A megadott hely nem támogatott"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "A hely már csatolva van"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "A hely nem csatolható"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Üres CD-ROM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Üres CD-R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Üres CD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Üres DVD-ROM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Üres DVD-RAM lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Üres DVD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Üres DVD+R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Üres DVD+RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Üres DVD+R DL lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Üres Blu-Ray lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Üres Blu-Ray R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Üres Blu-Ray RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Üres HD DVD lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Üres HD DVD-R lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Üres HD DVD-RW lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Üres MO lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Lemez"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Üres lemez"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s meghajtó"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Hajlékonylemezes meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Szoftveres RAID meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Szalagos meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz meghajtó"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Pen drive"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Tömeges tárolómeghajtó"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Az adathordozó kiadása meghiúsult, mivel néhány kötete foglalt."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Vegyes hang/adatlemez"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s adathordozó"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s titkosított adatok"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: hiba a fájl megnyitásakor: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, hiba a szabványos kimenetre íráskor"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: hiba a következő olvasásakor: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: hiba a következő lezárásakor: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "HELY… – HELYEK összefűzése a szabványos kimenetre."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"A helyeken található fájlok összefűzése és kiírása a szabványos kimenetre. A "
+"hagyományos cat segédprogramhoz hasonlóan működik, de helyi fájlok helyett "
+"gvfs helyeket használ: megadható például összefűzési helyként a smb://"
+"kiszolgáló/erőforrás/fájl.txt."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Megjegyzés: irányítsa keresztül a cat programon, ha annak formázási "
+"lehetőségeire van szükség, mint például a -n, -T vagy hasonlók."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: hiányzó helyek"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: hiba a hely megnyitásakor: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: hiba az alkalmazás indításakor: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FÁJLOK… – FÁJLOK megnyitása a bejegyzett alkalmazással."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"A fájlok megnyitása az adott fájltípus kezelésére bejegyzett alapértelmezett "
+"alkalmazással."
+
diff --git a/trunk/po/it.po b/trunk/po/it.po
new file mode 100644
index 00000000..e4d75046
--- /dev/null
+++ b/trunk/po/it.po
@@ -0,0 +1,1714 @@
+# Italian translation for gvfs.
+# Copyright (C) 2007, 2008, 2009, Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+# Luca Ferretti <elle.uca@libero.it>, 2007, 2008, 2009.
+#
+#
+# Da glib/gio
+# * seek --> posizionamento
+# * stream --> lasciato come tale, cfr
+# http://library.gnome.org/devel/gio/stable/streaming.html
+#
+# Nota: diversi messaggi di errore finiscono con "[...]: %s" In genere il %s
+# è sostituito con qualcosa che comincia con la maiuscola. Dove ho
+# controllato il codice ho messo il punto.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 1.1.x\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
+"product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-26 20:00+0000\n"
+"PO-Revision-Date: 2009-02-26 18:30+0100\n"
+"Last-Translator: Luca Ferretti <elle.uca@libero.it>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operazione non supportata, file su mount differenti"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Valore di ritorno non valido da get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Valore di ritorno non valido da query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Impossibile ottenere il descrittore di file dello stream"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Valore di ritorno non valido da open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Impossibile ottenere il descrittore di file dello stream"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Valore di ritorno non valido da call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Valore di ritorno non valido da get_filesystem_info"
+
+# corretta e pessima traduzione, ma in fondo quando vuoi
+# che vada a comparire all'utente??? speriamo mai...
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Impossibile trovare il mount includente"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nome file «%s» non valido"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Valore di ritorno non valido da query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Valore di ritorno non valido da monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Valore di ritorno non valido da monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "L'operazione è stata annullata"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Errore nel protocollo dello stream. %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Fine dello stream"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Posizionamento non supportato sullo stream"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "L'operazione di interrogazione informazioni non è supportata"
+
+# spero che sia così, anche perché query info l'ho tradotto
+# in modo diverso da quella appena sopra :-/
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Informazioni di interrogazione non supportate sullo stream"
+
+# %s --> Invalid reply (ma non reso traducibile..)
+# leggendo il codice è proprio le informazioni
+# sull'oggetto GMount
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Errore durante il recupero delle informazioni sul mount. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Errore nel connettersi al demone. %s"
+
+# GNOME-2-26
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Valore di ritorno non valido da open_icon_for_read"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Errore nel creare il socket. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Errore nel connettersi al socket. %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Formato informazioni file non valido"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Contenuto elenco informazioni attributi non valido"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Errore nell'inizializzare Avahi. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Errore nel creare il resolver Avahi. %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Errore nel risolvere «%s» per il servizio «%s» sul dominio «%s»"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Errore nel risolvere «%s» per il servizio «%s» sul dominio «%s». Uno o più "
+"record TXT risultano mancanti. Chiavi richieste: «%s»."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Tempo scaduto nel risolvere «%s» per il servizio «%s» sul dominio «%s»"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "encoded_triple dns-sd «%s» malformata"
+
+# tenere in sync con glib/gio
+#
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Impossibile gestire la versione %d della codifica GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Dati di input malformati da GVfsIcon"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Errore nel connettersi a D-Bus. %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Servizio file system %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Errore. %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Uso: %s --spawner ID-DBUS PERCORSO_OGGETTO"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Uso: %s CHIAVE=VALORE CHIAVE=VALORE ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Nessun tipo di mount specificato"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "punto di mount per %s già in esecuzione"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "errore nell'avviare il demone di mount"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "/ su %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "Nessun nome host specificato"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Specifica di mount non valida"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Il file non esiste"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Il file non è una directory"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Masterizzazione"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Impossibile creare la directory temporanea"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "File o directory inesistente"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Directory non vuota"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Impossibile copiare il file sulla directory"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Creazione CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Il file esiste"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operazione non supportata dal backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "File o directory inesistente nel percorso di destinazione"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Impossibile copiare la directory sulla directory"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Il file di destinazione esiste"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Impossibile copiare la directory ricorsivamente"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Non supportato"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Impossibile connettersi al bus di sistema"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Impossibile creare il contesto libhal"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Impossibile inizializzare libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nessuna unità specificata"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Impossibile trovare l'unità «%s»"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "L'unità «%s» non contiene file audio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "Mount cdda su %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disco audio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Il file system è occupato: %d file aperto"
+msgstr[1] "Il file system è occupato: %d file aperti"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "File «%s» inesistente sull'unità «%s»"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Errore da \"paranoia\" sull'unità «%s»"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Errore nel posizionarsi nello stream sull'unità «%s»"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "File inesistente"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Il file non esiste o non è una traccia audio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Servizio file system CD audio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "File system"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Impossibile aprire la directory"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Impossibile aprire il file montabile"
+
+# controllato codice, appaiono messaggi non traducibili (bug #572070)
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "Errore interno: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Impossibile montare il file"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Nessun supporto nell'unità"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Non è un file montabile"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Impossibile smontare il file"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Impossibile espellere il file"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Errore HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Impossibile analizzare la risposta"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Risposta vuota"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Replica inattesa dal server"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Risposta non valida"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Condivisione WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Inserire la password per %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Inserire la password per il proxy"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Non è una condivisione WebDAV abilitata"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV su %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Impossibile creare la richiesta"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Il file di destinazione esiste già"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Il file è stato modificato dall'esterno"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Creazione del file di backup non riuscita"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Rete locale"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Impossibile monitorare il file o la directory."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Rete"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Gli account non sono supportati"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Connessione chiusa dall'host"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Impossibile aprire la connessione dati. Forse è impedito dal proprio "
+"firewall."
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Connessione dati chiusa"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Operazione non riuscita"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Niente spazio rimasto sul server"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operazione non supportata"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Permesso negato"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Tipo di pagina sconosciuta"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nome file non valido"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Replica non valida"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "trasmissione interrotta"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "Impossibile connettersi all'host"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Inserire la password per ftp come %s su %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Inserire la password per ftp su %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Dialogo password annullato"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp su %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp come %s su %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "Il file è una directory"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "i backup non sono ancora supportati"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nome file troppo lungo"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nome file di destinazione non valido"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: la directory o il file esiste"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: file o directory inesistente"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: nome file non valido"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: non supportato"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Fotocamera digitale (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Fotocamera %s"
+
+# usato lettore perché tutti vendor
+# hanno "lettori mp3" nei cataloghi
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Lettore audio %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Fotocamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Lettore audio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Nessun dispositivo specificato"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Impossibile creare il contesto gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Errore nel creare la fotocamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Errore nel caricare le informazioni sul dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Errore nel consultare le informazioni sul dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Errore nell'ottenere le informazioni sul dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Errore nell'impostare la porta di comunicazione della fotocamera"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Errore nell'inizializzare la fotocamera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "Mount gphoto2 su %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Nessuna fotocamera specificata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Errore nel creare l'oggetto file"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Errore nell'ottenere il file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Errore nell'ottenere i dati dal file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificatore icona «%s» malformato"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Errore nel posizionarsi nello stream sulla fotocamera «%s»"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Non è una directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Recupero dell'elenco cartelle non riuscito"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Recupero dell'elenco dei file non riuscito"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Errore nel creare la directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Il nome esiste già"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Nuovo nome troppo lungo"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Errore nel rinominare la directory"
+
+# GNOME-2-24
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Errore nel rinominare il file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "La directory «%s» non è vuota"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Errore nell'eliminare la directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Errore nell'eliminare il file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Impossibile scrivere nella directory"
+
+# non sono molto sicuro di queste tre con append...
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Impossibile allocare il nuovo file su cui accodare"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Impossibile leggere il file su cui accodare"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Impossibile ottenere i dati del file su cui accodare"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Errore nello scrivere il file"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Non supportato (non è la stessa directory)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Non supportato (orig è directory, dest è directory)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Non supportato (orig è directory, dest è file esistente)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Non supportato (orig è file, dest è directory)"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Errore client HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codifica non valida)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Notifica delle directory non supportata"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Rete Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor posizioni di rete"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s su %s"
+
+# software omesso
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Supporto USB mancante. Contattare il proprio vendor"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Connessione al dispositivo persa"
+
+# a leggere i sorgenti sembra appaia solo per nokia 3650
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Il dispositivo richiede un aggiornamento software"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Il programma ssh è uscito in modo inatteso"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nome host sconosciuto"
+
+# Nota: instradamento è la traduzione glossariata
+# per route. Cfr http://tp.linux.it/glossario.html
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Nessun instradamento verso l'host"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Connessione rifiutata dal server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Verifica della chiave dell'host non riuscita"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Impossibile avviare il programma ssh"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Impossibile avviare il programma ssh. %s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr "Tempo scaduto durante l'accesso"
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr "Inserire la passphrase per la chiave"
+
+#: ../daemon/gvfsbackendsftp.c:857
+msgid "Enter password"
+msgstr "Inserire la password"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "Impossibile inviare la password"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "Accedi comunque"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Cancel Login"
+msgstr "Annulla accesso"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"L'identità del computer remoto (%s) è sconosciuta.\n"
+"Ciò accade quando si accede a un computer per la prima volta.\n"
+"\n"
+"L'identità inviata dal computer remoto è %s. Per essere assolutamente certi "
+"che sia sicuro continuare, contattare l'amministratore di sistema."
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "Dialogo di accesso annullato"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr "Impossibile inviare la conferma dell'identità dell'host"
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+msgid "Protocol error"
+msgstr "Errore di protocollo"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp per %s su %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp su %s"
+
+# NdT *un comando ssh supportato*
+# Controllato nel codice: prova diversi programmi tra cui
+# OpenSSH e SunSSH, ecco perché usato *un comando*
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr "Impossibile trovare un comando ssh supportato"
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "Fallimento"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "Ricevuta replica non valida"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id \"%s\" non valido in OpenIconForRead"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Errore nel creare il file di backup. %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "Impossibile creare il file temporaneo"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Impossibile spostare la directory sulla directory"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Richiesta password per condivisione %s su %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Errore interno (%s)"
+
+# NdT: Montaggio?? Montatura?? Montamento??
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Mount della condivisione Windows non riuscito"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Tipo di posizionamento non supportato"
+
+# Nota: quasi sicuramente dopo i : c'è una frase che inizia per maiuscola
+# (errore preso da GIO)
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Creazione del file di backup non riuscita. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Errore nell'eliminare il file. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Errore nello spostare il file. %s"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Errore nel rimuovere il file di destinazione. %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Impossibile spostare la directory ricorsivamente"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Servizio file system condivisioni Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Richiesta password per %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Condivisioni Windows su %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Recupero dell'elenco delle condivisioni dal server non riuscito"
+
+# aggiunto oggetto
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Il file non è un oggetto montabile"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Non è un file normale"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Servizio file system rete Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "La cartella cestino non può essere eliminata"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Gli oggetti nel cestino non possono essere modificati"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Cestino"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipo di backend non valido"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Errore nell'inviare il fd. %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Collegamenti simbolici non supportati dal backend"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Messaggio dbus non valido"
+
+# opzione --replace di gvfsd
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Sostituisce il vecchio demone."
+
+# opzione --no-fuse di gvfsd
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Non avvia fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Demone GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Demone principale per GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Provare \"%s --help\" per maggiori informazioni."
+
+# NdT. OK, sembra la bibbia....
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Argomenti non validi per il figlio generato"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Mount automatico non riuscito: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "La posizione specificata non è montata"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "La posizione specificata non è supportata"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "La posizione è già montata"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "La posizione non è montabile"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disco CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disco CD-ROM vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disco CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disco CD-R vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disco CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disco CD-RW vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disco DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disco DVD-ROM vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disco DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disco DVD-RAM vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disco DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disco DVD-RW vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disco DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disco DVD+R vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disco DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disco DVD+RW vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disco DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disco DVD+R DL vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disco Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disco Blu-Ray vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disco DVD HD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disco DVD HD vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disco DVD-R HD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disco DVD-R HD vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disco DVD-RW HD"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disco DVD-RW HD vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disco MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disco MO vuoto"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disco"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disco vuoto"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unità %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unità %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Unità floppy"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unità RAID software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unità USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Unità ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Unità SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unità FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unità a nastro"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unità CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unità MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unità SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unità SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unità Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unità Jaz"
+
+# in gnome-vfs era Pen Drive, tradotto Pendrive...
+# nella notazione HAL è 'flashkey', praticamente, credo
+# ogni chiavetta USB??
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Pendrive"
+
+# In base al codice, ogni drive che non è
+# riconosciuto come uno dei precedenti.
+#
+# Tolto "di massa" perché, dai, è inutile nella
+# traduzione di qualcosa che appare all'utente.
+#
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unità di memorizzazione"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Espulsione del supporto non riuscita: uno o più volumi sul supporto sono "
+"occupati."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+# misto e ibrido sono diversi
+#
+# http://en.wikipedia.org/wiki/Hybrid_disc
+# http://en.wikipedia.org/wiki/Mixed_mode
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disco misto audio/dati"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Supporto da %s"
+
+# Rigirato. Se qualcuno ha un drive cifato con LUKS
+# mi faccia sapere se funziona...
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s di dati cifrati"
+
+# molto probabile che dopo : appaia msg che comincia per maiuscola
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: errore nell'aprire il file. %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, errore nello scrivere su standard output"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: errore nel leggere. %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: errore nel chiudere. %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "POSIZIONE... - concatena le POSIZIONI sullo standard output."
+
+# aggiunto "indicate"
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatena i file sulle posizioni indicate e li stampa sullo standard output. "
+"Opera come la tradizionale utilità cat, ma usando posizioni gvfs invece di "
+"file locali: per esempio è possibile usare qualcosa come smb://server/"
+"risorsa/file.txt come posizione da concatenare."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: mettere in pipe con cat se si necessita delle opzioni di formattazione "
+"come -n, -T o altro."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: posizioni mancanti"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: errore nell'aprire la posizione. %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: errore nel lanciare l'applicazione. %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILE... - apre i FILE con l'applicazione registrata."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Apre i file con l'applicazione predefinita registrata per gestire quel tipo "
+"di file."
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (nel cestino)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Impossibile eliminare il cestino"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Notifica della directory cestino non supportata"
diff --git a/trunk/po/ja.po b/trunk/po/ja.po
new file mode 100644
index 00000000..45bba48e
--- /dev/null
+++ b/trunk/po/ja.po
@@ -0,0 +1,1635 @@
+# gvfs ja.po.
+# Copyright (C) 2008,2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+# Takeshi AIHANA <takeshi.aihana@gmail.com>, 2008,2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs trunk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-09 10:18+0900\n"
+"PO-Revision-Date: 2009-02-09 10:17+0900\n"
+"Last-Translator: Takeshi AIHANA <takeshi.aihana@gmail.com>\n"
+"Language-Team: Japanese <takeshi.aihana@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "サポートしていない操作です (ファイルが別々のマウント先にあります)"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "ストリーム・ファイルのディスクリプタを取得できませんでした"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "ストリーム・ファイルのディスクリプタを取得しませんでした"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info() の返り値が間違っています"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "エンクローズしているマウントが見つかりませんでした"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ファイル名が間違っています: %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir() の返り値が間違っています"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file() の返り値が間違っています"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "操作がキャンセルされた"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "ストリームのプロトコルでエラー: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "ストリームの最後"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "ストリーム上のシークはサポートしていません"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "query_info の操作はサポートしていません"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "ストリーム上での query_info はサポートしていません"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "マウント情報を取得する際にエラー: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "デーモンに接続する際にエラー: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read() の返り値が間違っています"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "ソケットを生成する際にエラー: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "ソケットに接続する際にエラー: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "ファイル情報の書式が間違っています"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "属性情報のリストにあるデータが間違っています"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi のデーモンを初期化できませんでした: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi のレソルバを生成できませんでした: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" な \"%s\" というサービスは \"%s\" というドメインにはありません"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" な \"%s\" というサービスは \"%s\" というドメインにはありませんでした: "
+"1つ以上の TXT レコードが不足しています: 必要なキーは \"%s\" です"
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"\"%s\" な \"%s\" というサービスを \"%s\" というドメインから検索しましたがタイ"
+"ムアウトになりました"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "DNS-SD の encoded_triple の形式が間違っています: '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "バージョン %d の GVfsIcon 型エンコーディングはサポートしていません"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon 型の入力データの形式が間違っています"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus に接続する際にエラー: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s のファイルシステム・サービス"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "エラー: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "用法: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "用法: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "マウントの種類が指定されていません"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s 用のマウントポイントは既に使用中です"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "マウント・デーモンお起動する際にエラー"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s の / (ルート)"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "ホスト名が指定されていません"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "マウントの仕様が間違っています"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ファイルがありません"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "そのファイルはディレクトリではありません"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Burn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "作業ディレクトリを生成できません"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "そのようなファイルまたはディレクトリは存在しません"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "ディレクトリが空ではありません"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ファイルをディレクトリの外にコピーできません"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD クリエータ"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "ファイルが存在しています"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "バックエンドでサポートしていない操作です"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "転送先のパスに、そのようなファイルまたはディレクトリは存在しません"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "ディレクトリをディレクトリの外にコピーできません"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "転送先にファイルが存在します"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "ディレクトリを再帰的にコピーできません"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "サポートしていません"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "システム・バスに接続できません"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "libhal のコンテキストを生成できません"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "libhal を初期化できません"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "ドライブが指定されていません"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "%s というドライブは見つかりません"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "%s というドライブには楽曲ファイルはありません"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda が %s にマウントしました"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "オーディオ・ディスク"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ファイルシステムが使用中です: %d 個のファイルがオープンしたままです"
+msgstr[1] "ファイルシステムが使用中です: %d 個のファイルがオープンしたままです"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "%s というファイルは %s というドライブに存在しません"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ドライブ (%s) の 'paranoia'でエラー"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ドライブ (%s) のストリームをシークする際にエラー"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "そのようなファイルは存在しません"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "そのファイルは存在しないか、もしくはオーディオ・トラックではありません"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "オーディオ CD のファイルシステム・サービス"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "コンピュータ"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ファイルシステム"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "ディレクトリをオープンできません"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "マウント可能なファイルをオープンできません"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "システム内部のエラー: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ファイルをマウントできません"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ドライブにメディアが挿入されていません"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "マウント可能なファイルは存在しません"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ファイルをアンマウントできません"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ファイルを取り出せません"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP のエラー: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "応答メッセージを解析できませんでした"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "応答メッセージが空です"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "サーバからの想定外のリプライです"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "応答メッセージが間違っています"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV 共有"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s のパスワードを入力して下さい"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "プロキシのパスワードを入力して下さい"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV 共有は利用できません"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s での WebDAV 共有"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "要求メッセージを生成できませんでした"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "対象のファイルが既に存在しています"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "そのファイルは他のプロセスで変更されました"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "バックアップ・ファイルの生成に失敗しました"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "ローカル・ネットワーク"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ファイルまたはディレクトリを監視できません"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "ネットワーク"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "アカウントがサポートされていません"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "ホストが接続を閉じました"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"データの接続を開始できません (おそらくファイヤーウォールが邪魔していると思わ"
+"れます)"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "データの接続を閉じました"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "操作が失敗しました"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "サーバの容量が足りません"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "サポートしていない操作です"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "権限がありません"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "ページの種類が不明です"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "ファイル名が間違っています"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "リプライが間違っています"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "送信エラー"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "ホストに接続できませんでした"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "%s@%s のパスワードを入力指定下さい"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "FTP@%s のパスワードを入力指定下さい"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "パスワード・ダイアログがキャンセルしました"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp (%s)"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp (%s@%s)"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "ファイルはディレクトリです"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "バックエンドは未だサポートしていません"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ファイル名が長すぎます"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "転送先のファイル名が間違っています"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ディレクトリまたはファイルが存在します"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: そのようなファイルまたはディレクトリは存在しません"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ファイル名が間違っています"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: 未サポートです"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "デジカメ (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s 製のカメラ"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s 製のオーディオ・プレイヤー"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "カメラ"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "オーディオ・プレイヤー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "デバイスが指定されていません"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 のコンテキストを生成できません"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "カメラ・オブジェクトを生成できません"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "デバイス情報を読み込む際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "デバイス情報を検索する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "デバイス情報を取得する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "カメラに接続するポートを設定する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "カメラのオブジェクトを初期化する際にエラー"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 が %s にマウントしました"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "カメラが指定されていません"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "ファイル・オブジェクトを生成する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "ファイルを取得する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "ファイルのデータを取得する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "アイコンの識別子の形式が間違っています: '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "カメラ (%s) のストリームを検索する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "ディレクトリではありません"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "フォルダの一覧を取得できませんでした"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "ファイルの一覧を取得できませんでした"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "ディレクトリを生成する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "既に存在しています"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "新しい名前が長すぎます"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "ディレクトリ名を変更する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "ファイル名を変更する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "ディレクトリ (%s) は空ではありません"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "ディレクトリを削除する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "ファイルを削除する際にエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "ディレクトリに書き込めません"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "追加先の新しいファイルを確保できません"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "追加先のファイルを読み込めません"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "追加先のファイルのデータを取得できません"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "ファイルの書き込みでエラー"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "未サポートです (同じディレクトリではありません)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "未サポートです (転送元と転送先の双方がディレクトリ)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "未サポートです (転送元がディレクトリで転送先がファイル)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "未サポートです (転送元がファイルで転送先がディレクトリ)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP クライアントのエラー: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (エンコーディングが間違っています)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ディレクトリ通知はサポートしていません"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows ネットワーク"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "ネットワーク・ロケーション・モニタ"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s@%s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+"USB をサポートしていません; 本ライブラリを提供しているベンダに問い合わせて下"
+"さい"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "デバイスへの接続が失われました"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "デバイス・ソフトウェアを更新して下さい"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh プログラムが突然終了しました"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "ホスト名が不明です"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "ホストへの経路がありません"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "サーバが接続を拒否しました"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "ホストの鍵を検証できませんでした"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh プログラムに fork() できませんでした"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh プログラムに fork() できませんでした: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "ログインがタイムアウトしました"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "鍵のパスフレーズを入力して下さい"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "パスワードを入力して下さい"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "パスワードを送信できません"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "とにかくログインする"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "ログインをキャンセルする"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"リモートのコンピュータ (%s) を一意に識別できません\n"
+"(これは、初めてコンピュータにログインした時に発生します)\n"
+"\n"
+"リモートのコンピュータが送信してきた ID は %s です\n"
+"この ID のコンピュータがセキュリティ的に安全であるか\n"
+"確認したい場合は、システム管理者に連絡してみて下さい"
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "ログイン・ダイアログがキャンセルしました"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "ホストの身元を確認できません"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "プロトコルのエラーです"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp (%s@%s)"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp (%s)"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "ssh コマンドが見つかりません"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "失敗"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "受信したリプライが間違っています"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead にあるアイコンの識別子が不正です: '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "バックアップ・ファイルを生成する際にエラー: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "作業ファイルを生成できません"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "ディレクトリをディレクトリの外に移動できません"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s@%s を共有するにはパスワードが必要です"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "内部エラー (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows 共有をマウントできませんでした"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "サポートしていないシークの種類です"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "バックアップ・ファイルの生成に失敗しました: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ファイルを削除する際にエラー: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ファイルを移動する際にエラー: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "対象のファイルを削除する際にエラー: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "ディレクトリを再帰的に移動できません"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows 共有のファイルシステム・サービス"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s のパスワードを入力して下さい"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows 共有@%s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "サーバから共有リストを取得できませんでした"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "そのファイルはマウントできません"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "通常のファイルではありません"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows ネットワークのファイルシステム・サービス"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "ゴミ箱フォルダは削除できません"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "ゴミ箱の中にあるアイテムは変更できません"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "ゴミ箱"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "バックエンドの種類が間違っています"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd を送信する際にエラー: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "バックエンドはシンボリック・リンクをサポートしていません"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "D-Bus のメッセージが間違っています"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "古いデーモンを置きかえる"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "fuse を起動しない"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS デーモン"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS のメイン・デーモン"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "詳細は \"%s --help\" の出力を確認して下さい"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "fork() した子プロセスの引数が間違っています"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "自動マウントに失敗しました: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "指定した場所はマウントされていません"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "指定した場所はサポートされていません"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "その場所は既にマウントされています"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "その場所はマウントできません"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "空の CD-ROM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "空の CD-R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "空の CD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "空の DVD-ROM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "空の DVD-RAM ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "空の DVD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "空の DVD+R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "空の DVD+RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "空の DVD+R DL ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "空の Blu-Ray ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "空の Blu-Ray R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "空の Blu-Ray RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "空の HD DVD ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "空の HD DVD-R ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "空の HD DVD-RW ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "空の MO ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "ディスク"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "空のディスク"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ドライブ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "フロッピー・ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "ソフトウェア RAID ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "テープ・ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "マス・ストレージ・ドライブ"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"メディアを取り出せませんでした (メディアで1つ以上のボリュームが使用中です)"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "楽曲とデータの混合ディスク"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s のメディア"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s の暗号化されたデータ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ファイルをオープンする際にエラー: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s (標準出力に出力する際にエラー)"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: 読み込む際にエラー: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:クローズする際にエラー: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATIONs... - 複数の URI を連結して標準出力に出力する"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"指定した場所 (URI) にある複数のファイルを連結して標準出力に表示する\n"
+"基本的に UNIX の cat コマンドのような動作をするが\n"
+"指定できる URI はローカルのファイルではなく、gvfs 経由で\n"
+"指定できる URI である\n"
+"例: smb://server/resource/file.txt"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"注意: -n や -T などの書式を変更するオプションを指定した場合\n"
+" ローカルの cat コマンドにパイプで渡すだけである"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: URI を指定して下さい"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: URI をオープンする際にエラー: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: アプリケーションを起動する際にエラー: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - 登録したアプリで複数の FILE を開く"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"指定したファイルを扱うデフォルトのアプリケーションで\n"
+"それらのファイルを開く"
diff --git a/trunk/po/kn.po b/trunk/po/kn.po
new file mode 100644
index 00000000..b3f146c5
--- /dev/null
+++ b/trunk/po/kn.po
@@ -0,0 +1,1529 @@
+# translation of gvfs.gnome-2-24.po to Kannada
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Shankar Prasad <svenkate@redhat.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.gnome-2-24\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-18 11:04+0000\n"
+"PO-Revision-Date: 2008-09-19 17:50+0530\n"
+"Last-Translator: Shankar Prasad <svenkate@redhat.com>\n"
+"Language-Team: Kannada <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ಅಮಾನ್ಯವಾದ ಕಡತದ ಹೆಸರು %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1087 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:757
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "ಡೀಮನ್‌ಗೆ ಸಂಪರ್ಕ ಹೊಂದುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "ಸಾಕೆಟ್‌ ಅನ್ನು ನಿರ್ಮಿಸುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "ಸಾಕೆಟ್‌ನೊಂದೊಗೆ ಸಂಪರ್ಕ ಹೊಂದುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "ಅಮಾನ್ಯವಾದ ಕಡತದ ಮಾಹಿತಿ ವಿನ್ಯಾಸ"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Busನೊಂದಿಗೆ ಸಂಪರ್ಕ ಹೊಂದುವಲ್ಲಿ ದೋಷ: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ಕಡತವ್ಯವಸ್ಥೆ ಸೇವೆ"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ದೋಷ: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ಬಳಕೆ: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ಬಳಕೆ: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ಯಾವುದೆ ಆರೋಹಣಾ ಬಗೆಯನ್ನು ಸೂಚಿಸಲಾಗಿಲ್ಲ"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ %s ನಲ್ಲಿ"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:623
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "ಕಡತ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr ""
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, c-format
+msgid "No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD ರಚನಾಕಾರ"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "ಕಡತವು ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobpull.c:173 ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135 ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149 ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119 ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150 ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122 ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Cannot initialize libhal"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "ಆಡಿಯೋ ಡಿಸ್ಕ್‍"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr ""
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "ಗಣಕ"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ಕಡತವ್ಯವಸ್ಥೆ"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:666
+#: ../daemon/gvfsbackendtrash.c:678 ../daemon/gvfsbackendtrash.c:1786
+msgid "Can't open directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "ಆಂತರಿಕ ದೋಷ: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ದೋಷ: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr "WebDAV ಹಂಚಿಕೆ"
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s ಗಾಗಿ ಗುಪ್ತಪದವನ್ನು ನಮೂದಿಸಿ"
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s ನಲ್ಲಿ WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1822
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1056
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1092
+#: ../daemon/gvfsbackendsmb.c:1839
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "ಜಾಲಬಂಧ"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "ಅನುಮತಿಯು ನಿರಾಕರಿಸಲ್ಪಟ್ಟಿದೆ"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ಅಮಾನ್ಯವಾದ ಕಡತದ ಹೆಸರು"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ಬೆಂಬಲವಿಲ್ಲ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ಡಿಜಿಟಲ್ ಕ್ಯಾಮೆರಾ (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s ಕ್ಯಾಮೆರಾ"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ಆಡಿಯೋ ಪ್ಲೇಯರ್"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "ಕ್ಯಾಮೆರಾ"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "ಆಡಿಯೋ ಪ್ಲೇಯರ್"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+msgid "Failed to get folder list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+msgid "Error creating camera"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+msgid "Error loading device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+msgid "Error getting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2080
+msgid "Failed to get file list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+msgid "Error creating directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+msgid "Name already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+msgid "New name too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+msgid "Error deleting directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+msgid "Can't write to directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+msgid "Not supported (not same directory)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP ಕ್ಲೈಂಟ್ ದೋಷ: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1319 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ಅಮಾನ್ಯವಾದ ಎನ್ಕೋಡಿಂಗ್)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ಕೋಶದ ಸೂಚನೆ ನೀಡುವಿಕೆಗೆ ಬೆಂಬಲವಿಲ್ಲ"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "ವಿಂಡೋಸ್ ಜಾಲಬಂಧ"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "ಸ್ಥಳೀಯ ಜಾಲಬಂಧ"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:528
+#: ../daemon/gvfsbackendsmb.c:1312
+#, c-format
+msgid "%s on %s"
+msgstr "%s, %s ನಲ್ಲಿ"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "ಸಾಧನದೊಂದಿಗಿನ ಸಂಪರ್ಕವು ತಪ್ಪಿಹೋಗಿದೆ"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "ಸಾಧನಕ್ಕೆ ಒಂದು ತಂತ್ರಾಂಶ ಅಪ್ಡೇಟಿನ ಅಗತ್ಯವಿದೆ"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "ssh ಪ್ರೊಗ್ರಾಂ ಅನಿರೀಕ್ಷಿತವಾಗಿ ನಿರ್ಗಮಿಸಿದೆ"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "ಅತಿಥೇಯದ ಹೆಸರು ತಿಳಿದಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "ಅತಿಥೇಯಕ್ಕೆ ಯಾವುದೆ ಮಾರ್ಗವಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "ಪರಿಚಾರಕದಿಂದ ಸಂಪರ್ಕವು ನಿರಾಕರಿಸಲ್ಪಟ್ಟಿದೆ"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "ಅತಿಥೇಯ ಕೀಲಿಯ ಪರಿಶೀಲನೆಯು ವಿಫಲಗೊಂಡಿದೆ"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "ಕೀಲಿಗಾಗಿ ಗುಪ್ತವಾಕ್ಯವನ್ನು ನಮೂದಿಸಿ"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "ಗುಪ್ತಪದವನ್ನು ನಮೂದಿಸಿ"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "ಗುಪ್ತಪದವನ್ನು ಕಳುಹಿಸಲಾಗಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "ಪರವಾಗಿಲ್ಲ ಪ್ರವೇಶಿಸು"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "ಪ್ರವೇಶವನ್ನು ರದ್ದುಗೊಳಿಸು"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "ಪ್ರೊಟೋಕಾಲ್ ದೋಷ"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "%s ನಲ್ಲಿ sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "ಬೆಂಬಲಿತವಾದ ssh ಆಜ್ಞೆಯನ್ನು ಪತ್ತೆ ಮಾಡುವಲ್ಲಿ ವಿಫಲತೆ"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "ವಿಫಲತೆ"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "ಅಮಾನ್ಯವಾದ ಪ್ರತ್ಯುತ್ತರವನ್ನು ಪಡೆಯಲಾಗಿದೆ"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "ಬ್ಯಾಕ್ಅಪ್ ಕಡತವನ್ನು ನಿರ್ಮಿಸುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "ತಾತ್ಕಾಲಿಕ ಕಡತವನ್ನು ನಿರ್ಮಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1811
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:213
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:468 ../daemon/gvfsbackendsmb.c:514
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "ಆಂತರಿಕ ದೋಷ (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:587
+msgid "Failed to mount Windows share"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:735 ../daemon/gvfsbackendsmb.c:1191
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1255
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1713
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ಕಡತವನ್ನು ಅಳಿಸುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1787
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ಕಡತವನ್ನು ಸ್ಥಳಾಂತರಿಸುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1859
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1883
+msgid "Can't recursively move directory"
+msgstr "ಪುನರಾವರ್ತಿತವಾಗಿ ಕೋಶವನ್ನು ಸ್ಥಳಾಂತರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendsmb.c:1946
+msgid "Windows Shares Filesystem Service"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "ಆರೋಹಿಸಲು ಸಾಧ್ಯವಿರದ ಕಡತ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "ಒಂದು ಸಾಮಾನ್ಯವಾದ ಕಡತವಲ್ಲ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "ವಿಂಡೋಸ್ ಜಾಲಬಂಧ ಕಡತವ್ಯವಸ್ಥೆ ಸೇವೆ"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "ಕಸಬುಟ್ಟಿ"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (ಕಸದಬುಟ್ಟಿಯಲ್ಲಿ)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "ಕಸದಬುಟ್ಟಿಯನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "ಅಮಾನ್ಯವಾದ ಬ್ಯಾಕ್ಎಂಡ್ ಬಗೆ"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd ಅನ್ನು ಕಳುಹಿಸುವಲ್ಲಿ ದೋಷ: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "ಅಮಾನ್ಯವಾದ dbus ಸಂದೇಶ"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "ಹಳೆಯ ಡೀಮನ್ ಅನ್ನು ಬದಲಾಯಿಸು."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS ಡೀಮನ್"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS ಗಾಗಿನ ಮುಖ್ಯ ಡೀಮನ್"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ \"%s --help\" ಅನ್ನು ನೋಡಿ."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "ಸ್ವಯಂಆರೋಹಣ ವಿಫಲಗೊಂಡಿದೆ: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "ಸೂಚಿಸಲಾದ ಸ್ಥಳವು ಆರೋಹಿತವಾಗಿಲ್ಲ"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "ಸೂಚಿಸಲಾದ ಸ್ಥಳವು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "ಸ್ಥಳವು ಈಗಾಗಲೆ ಆರೋಹಿತವಾಗಿದೆ"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "ಸ್ಥಳವನ್ನು ಆರೋಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "ಬ್ಲೂ-ರೇ"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "ಬ್ಲೂ-ರೇ-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "ಬ್ಲೂ-ರೇ-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ಡ್ರೈವ್"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ಫ್ಲಾಪಿ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "ಸಾಫ್ಟ್‍ವೇರ್ RAID ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "ಫೈರ್ವೈರ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "ಟೇಪ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "ಕಾಂಪ್ಯಾಕ್ಟ್‍ಫ್ಲ್ಯಾಶ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "ಮೆಮೊರಿಸ್ಟಿಕ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "ಸ್ಮಾರ್ಟ್-ಮೀಡಿಯಾ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "ಝಿಪ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "ಜಾಝ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "ತಂಬ್ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "ಸಮೂಹ ಶೇಖರಣಾ ಡ್ರೈವ್"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "ಮಾಧ್ಯಮವನ್ನು ಹೊರತಳ್ಳಲು ವಿಫಲಗೊಂಡಿದೆ; ಮಾಧ್ಯಮದಲ್ಲಿ ಒಂದು ಅಥವ ಹೆಚ್ಚಿನ ಪರಿಮಾಣಗಳು ಕಾರ್ಯನಿರತವಾಗಿವೆ."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "ಆಡಿಯೋ/ದತ್ತಾಂಶ ಮಿಶ್ರಿತ ಡಿಸ್ಕ್‍"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s ಮಾಧ್ಯಮ"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s ಗೂಢಲಿಪೀಕರಣ ದತ್ತಾಂಶ"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ಖಾಲಿ CD-ROM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ಖಾಲಿ CD-R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ಖಾಲಿ CD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ಖಾಲಿ DVD-ROM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ಖಾಲಿ DVD-RAM ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ಖಾಲಿ DVD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ಖಾಲಿ DVD+R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ಖಾಲಿ DVD+RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ಖಾಲಿ DVD+R DL ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "ಬ್ಲೂ-ರೇ ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ಖಾಲಿ ಬ್ಲೂ-ರೇ ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "ಬ್ಲೂ-ರೇ R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ಖಾಲಿ ಬ್ಲೂ-ರೇ R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "ಬ್ಲೂ-ರೇ RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ಖಾಲಿ ಬ್ಲೂ-ರೇ RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ಖಾಲಿ HD DVD ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ಖಾಲಿ HD DVD-R ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ಖಾಲಿ HD DVD-RW ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ಖಾಲಿ MO ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "ಡಿಸ್ಕ್‍"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ಖಾಲಿ ಡಿಸ್ಕ್‍"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ಕಡತವನ್ನು ತೆರೆಯುವಲ್ಲಿ ದೋಷ: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout ಗೆ ಬರೆಯುವಲ್ಲಿ ದೋಷ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: ಓದುವಲ್ಲಿ ದೋಷ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:ಮುಚ್ಚುವಲ್ಲಿ ದೋಷ: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ಕಾಣೆಯಾದ ಸ್ಥಳಗಳು"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: ಸ್ಥಳವನ್ನು ತೆರೆಯುವಲ್ಲಿ ದೋಷ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: ಅನ್ವಯವನ್ನು ಆರಂಭಿಸುವಲ್ಲಿ ದೋಷ: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - ನೋಂದಾಯಿಸಲಾದ ಅನ್ವಯಗಳಿಂದೊಗೆ FILES ತೆರೆ."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
diff --git a/trunk/po/ko.po b/trunk/po/ko.po
new file mode 100644
index 00000000..e772da95
--- /dev/null
+++ b/trunk/po/ko.po
@@ -0,0 +1,1661 @@
+# gvfs korean translation.
+# This file is distributed under the same license as the gvfs package.
+#
+# Young-Ho Cha <ganadist@gmail.com>, 2008.
+# Changwoo Ryu <cwryu@debian.org>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-18 09:10+0900\n"
+"PO-Revision-Date: 2009-02-18 09:11+0900\n"
+"Last-Translator: Changwoo Ryu <cwryu@debian.org>\n"
+"Language-Team: GNOME Korea <gnome-kr-hackers@lists.kldp.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "동작을 지원하지 않습니다. 파일이 각각 다른곳에 마운트되어 있습니다"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "파일 기술자 스트림을 얻을 수 없습니다"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "열기에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "파일 기술자 스트림을 얻을 수 없습니다"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "호출에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info에서 잘못된 반환값"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "둘러싸인 마운트를 찾을 수 없습니다"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "잘못된 파일 이름 %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir에서 잘못된 반환값"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file에서 잘못된 반환값"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "동작이 취소되었습니다"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "스트림 프로토콜의 오류: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "스트림의 끝"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "스트림에서는 찾기를 지원하지 않습니다"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "정보 질의 동작을 지원하지 않습니다"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "스트림에서는 정보 질의를 지원하지 않습니다"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "마운트 정보를 얻는 중 오류: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "데몬에 연결하는 데 오류: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read에서 잘못된 반환값"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "소켓을 만드는 데 오류: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "소켓에 연결하는 데 오류: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "잘못된 파일 정보 형식"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "잘못된 속성 정보 목록 내용"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi 초기화 오류: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi resolver를 만드는 데 오류: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"\"%s\" 타입의 \"%s\" 서비스를 찾는 데 오류가 발생했습니다 (도메인 \"%s\")"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" 타입의 \"%s\" 서비스를 찾는 데 오류가 발생했습니다 (도메인 \"%s\"). 필"
+"요한 TXT 레코드가 없습니다. 필요한 키는: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+"\"%s\" 타입의 \"%s\" 서비스를 찾는 데 제한 시간이 초과했습니다 (도메인 \"%s"
+"\")"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "DNS-SD encoded_triple 형태가 잘못되었습니다: '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon 인코딩의 %d 버전을 처리할 수 없습니다"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon의 입력 데이터 형태가 잘못되었습니다"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus에 연결하는 데 오류: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s 파일 시스템 서비스"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "오류: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "사용법: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "사용법: %s 키=값 키=값 ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "마운트 형식을 지정하지 않았습니다"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s의 마운트 위치에 이미 실행중입니다"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "마운트 데몬 시작하는 데 오류"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s의 /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "호스트 이름을 지정하지 않았습니다"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "잘못된 마운트 spec 파일"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "파일이 없습니다"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "파일이 디렉터리가 아닙니다"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "굽기"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "임시 디렉터리를 만들 수 없습니다"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "그런 파일이나 디렉터리가 없습니다"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "디렉터리가 비어있지 않습니다"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "디렉터리에 파일을 복사할 수 없습니다"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD 굽기"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "파일이 있습니다"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "백엔드에서 지원하는 동작이 아닙니다"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "해당 경로에 파일이나 디렉터리가 없습니다"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "디렉터리에 디렉터리를 복사할 수 없습니다"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "해당 파일이 있습니다"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "디렉터리를 되풀이해서 복사할 수 없습니다"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "지원하지 않음"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "시스템 버스에 연결할 수 없습니다"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "libhal 컨텍스트를 만들 수 없습니다"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "libhal을 초기화 할 수 없습니다"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "드라이브를 지정하지 않았습니다"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "드라이브 %s(을)를 찾을 수 없습니다"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "드라이브 %s에 음악 파일이 없습니다"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s의 cdda 마운트"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "음악 디스크"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "파일시스템이 사용 중입니다: %d개의 파일이 열림"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "드라이브 %2$s에 %1$s 파일이 없습니다"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "드라이브 %s에서 'paranoia'의 오류"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "드라이브 %s에서 스트림 찾는데 오류"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "그런 파일이 없습니다"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "파일이 없거나 음악 트랙이 아닙니다."
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "오디오 CD 파일 시스템 서비스"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "컴퓨터"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "파일 시스템"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "디렉터리를 열 수 없습니다"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "마운트 가능한 파일을 열 수 없습니다"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "내부 오류: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "파일을 마운트할 수 없습니다"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "드라이브에 매체가 없습니다"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "마운트 할 수 없는 파일"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "파일을 마운트 해제할 수 없습니다"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "파일을 꺼낼 수 없습니다"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP 오류: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "응답을 분석할 수 없습니다"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "비어있는 응답"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "서버에서 예측하지 못한 응답"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "잘못된 응답"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "웹 공유"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s의 암호를 입력하십시오"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "프록시 암호를 입력하십시오"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "웹 공유 디렉토리가 아닙니다"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s의 웹 공유"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "요청을 만들 수 없습니다"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "해당 파일이 이미 있습니다"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "파일이 외부에서 수정되었습니다"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "예비 파일 만드는데 실패했습니다"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "로컬 네트워크"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "파일이나 디렉터리를 감시할 수 없습니다."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "DNS-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "네트워크"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "계정을 지원하지 않습니다"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "호스트의 연결이 끊겼습니다"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "데이터 연결을 열 수 없습니다. 방화벽이 연결을 방해하는 것 같습니다."
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "데이터 연결이 끊겼습니다"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "동작이 실패하였습니다"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "서버에 남은 공간이 없습니다"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "지원하는 동작이 아닙니다"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "허가권이 거부되었습니다"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "알 수 없는 페이지 형식"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "잘못된 파일 이름"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "잘못된 응답"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "전송이 깨어짐"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "호스트에 연결할 수 없습니다"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "ftp의 암호를 입력하십시오 (사용자 %s, 호스트 %s)"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "ftp의 암호를 입력하십시오 (호스트 %s)"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "암호 입력 대화상자가 취소되었습니다"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp, 호스트 %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp, 로그인 %s, 호스트 %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "파일이 디렉터리입니다"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "예비파일을 아직 지원하지 않습니다"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "파일 이름이 너무 깁니다"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "잘못된 목표 파일 이름"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: 디렉터리나 파일이 있습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: 그런 파일이나 디렉터리가 없습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: 잘못된 파일 이름"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: 지원하지 않음"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "디지털 카메라 (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s 카메라"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s 오디오 재생기"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "카메라"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "오디오 재생기"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "장치를 지정하지 않았습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 컨텍스트를 만들 수 없습니다"
+
+# FIXME
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "카메라 만들기 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "장치 정보를 읽는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "장치 정보를 찾아보는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "장치 정보를 얻는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "카메라 통신포트를 설정하는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "카메라 초기화 중 오류"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s의 gphoto2 마운트"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "카메라를 지정하지 않았습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "파일 개체 만드는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "파일 얻는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "파일 데이터를 얻는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "아이콘 ID 형태가 잘못되었습니다: '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "카메라 %s에서 스트림 찾는데 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "디렉터리가 아닙니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "폴더 목록 얻기 실패"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "파일 목록 얻는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "디렉터리 만드는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "해당 이름이 이미 있습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "새 이름이 너무 깁니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "디렉토리 이름 바꾸는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "파일 이름 바꾸는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "디렉터리 '%s'(이)가 비어있지 않습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "디렉터리 지우는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "파일 지우는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "디렉터리를 쓸 수 없습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "덧붙이려는 새 파일을 할당할 수 없습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "덧붙이려는 파일을 읽을 수 없습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "덧붙이려는 파일의 데이터를 얻을 수 없습니다"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "파일 쓰는 중 오류"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "지원하지 않음 (같은 디렉터리가 아님)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "지원하지 않음 (원본은 디렉토리, 대상은 디렉토리) "
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "지원하지 않음 (원본은 디렉토리, 대상은 이미 있는 파일)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "지원하지 않음 (원본은 파일, 대상은 디렉터리)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP 클라이언트 오류: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (잘못된 인코딩)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "디렉터리 알림을 지원하지 않습니다"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "윈도 네트워크"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "네트워크 위치 감시기"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%2$s의 %1$s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB 지원 기능이 없습니다. 소프트웨어 공급처에 문의하십시오"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "장치의 연결이 끊겼습니다"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "장치에 연결하려면 소프트웨어 업데이트가 필요합니다"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh 프로그램이 예상치 않게 끝났습니다"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "호스트 이름을 알 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "호스트의 경로를 찾을 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "서버에서 연결이 거부되었습니다"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "호스트 키 확인이 실패했습니다"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh프로그램을 실행할 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh프로그램을 실행할 수 없습니다: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "로그인 할 때 시간제한이 걸렸습니다"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "ssh키 비밀번호를 입력하십시오"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "암호를 입력하십시오"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "암호를 보낼 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "그래도 로그인"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "로그인 취소"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"원격 컴퓨터(%s)의 신원을 알 수가 없습니다.\n"
+"로그인하려는 컴퓨터에 처음 연결하는 것 같습니다.\n"
+"\n"
+"원격 컴퓨터의 신원은 %s입니다. 계속해서 안전하게 사용하려면 시스템 관리자에"
+"게 문의하십시오."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "로그인 대화상자가 취소되었습니다"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "호스트 신원 확인을 보낼 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "프로토콜 오류"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp, 로그인 %s, 호스트 %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp, 호스트 %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "지원되는 ssh 명령을 찾을 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "실패"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "잘못된 응답을 받았습니다"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead의 icon_id가 잘못되었습니다: '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "예비 파일을 만드는 중 오류: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "임시 파일을 만들 수 없습니다"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "디렉터리에 디렉터리를 옮길 수 없습니다"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%2$s의 %1$s에 연결하려면 암호가 필요합니다"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "내부 오류 (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "윈도 공유를 마운트 하는데 실패했습니다"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "지원하지 않는 찾기 형식"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "예비 파일을 만드는데 실패했습니다: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "파일을 지우는데 오류: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "파일을 옮기는 데 오류: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "해당 파일을 지우는 데 오류: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "디렉터리를 되풀이해서 옮길 수 없습니다"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "윈도 공유 파일 시스템 서비스"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s에 연결하려면 암호가 필요합니다"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s의 윈도 공유"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "서버에서 공유 목록을 가져오는 데 실패했습니다"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "파일을 마운트할 수 없습니다"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "보통 파일이 아닙니다"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "윈도 네트워크 파일 시스템 서비스"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "휴지통 폴더는 삭제할 수 없습니다"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "휴지통의 항목을 수정할 수 없습니다"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "휴지통"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "잘못된 백엔드 형식"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd를 보내는 데 오류: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "백엔드에서 심볼릭 링크를 지원하지 않습니다"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "잘못된 DBUS 메시지"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "이전 데몬을 바꿉니다."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "FUSE를 시작하지 않습니다."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS 데몬"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS 기본 데몬"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "더 많은 정보를 보려면 \"%s --help\"를 사용하십시오."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "생성된 자식에서 잘못된 인자"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "자동 마운트 실패: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "지정한 위치를 마운트하지 않았습니다"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "지정한 위치를 지원하지 않았습니다"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "위치가 이미 마운트되어 있습니다"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "위치가 마운트 가능하지 않습니다"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "빈 CD-ROM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "빈 CD-R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "빈 CD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "빈 DVD-ROM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "빈 DVD-RAM 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "빈 DVD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "빈 DVD+R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "빈 DVD+RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "빈 DVD+R DL 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "블루레이 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "빈 블루레이 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "블루레이 R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "블루레이 R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "블루레이 RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "빈 블루레이 RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "빈 HD DVD 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "빈 HD DVD-R 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "빈 HD DVD-RW 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "광자기 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "빈 광자기 디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "디스크"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "빈 디스크"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "블루레이"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "블루레이-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "블루레이-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s 드라이브"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "플로피 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "소프트웨어 레이드 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "테이프 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CF 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "메모리스틱 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "스마트미디어 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "USB 메모리"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "대용량 저장장치 드라이브"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "미디어 꺼내기 실패: 미디어의 볼륨이 사용중입니다."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "오디오와 데이터가 섞인 디스크"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s 미디어"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s 암호화한 자료"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: 파일 여는데 오류: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, 표준 출력으로 쓰는데 오류"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: 읽는 데 오류: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:닫는 중 오류: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - 위치에 있는 파일들을 합쳐서 표준출력으로 출력합니다."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"지정한 위치의 파일을 합쳐서 표준출력으로 출력합니다. 전통적인 cat 도구처럼 동"
+"작합니다만, 로컬 파일대신 gvfs위치를 사용합니다: 합쳐질 파일 위치를 smb://"
+"server/resource/file.txt 같은 것으로 사용할 수 있습니다."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"알림: -n, -T, 등과 같은 형식 출력 옵션이 필요하면 파이프를 통해서 cat과 같이 "
+"실행하십시오."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: 위치를 입력하지 않았습니다"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: 위치 열기 오류: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: 프로그램 실행 오류: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - 등록된 프로그램으로 파일을 엽니다."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "파일의 형식을 처리하는 등록된 기본 프로그램으로 파일을 엽니다."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "휴지통은 지울 수 없습니다"
+
+#~ msgid "Can't pull trash"
+#~ msgstr "휴지통을 가져올 수 없습니다"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "(휴지통에 있는) %s"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "휴지통 디렉토리 알림을 지원하지 않습니다"
+
+#~ msgid "File unavailable"
+#~ msgstr "파일을 얻을 수 없습니다"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB 미디어"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB 미디어"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB 미디어"
+
+#~ msgid "Invalid reply from server."
+#~ msgstr "서버에서 잘못된 응답을 받았습니다."
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "%s의 음악 디스크"
+
+#~ msgid "The file does not exist"
+#~ msgstr "파일이 없습니다"
diff --git a/trunk/po/ku.po b/trunk/po/ku.po
new file mode 100644
index 00000000..b26563c3
--- /dev/null
+++ b/trunk/po/ku.po
@@ -0,0 +1,1362 @@
+# translation of ku.po to Kurdish
+# Copyright (C) 2008 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Erdal Ronahi <erdal dot ronahi at gmail dot com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: ku\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-20 13:52+0000\n"
+"PO-Revision-Date: 2008-03-21 02:04+0100\n"
+"Last-Translator: Erdal Ronahi <erdal dot ronahi at gmail dot com>\n"
+"Language-Team: Kurdish <ku@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural= n != 1;"
+
+#: ../client/gdaemonfile.c:464 ../client/gdaemonfile.c:1867
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:758
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:865
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:897 ../client/gdaemonfile.c:967
+#: ../client/gdaemonfile.c:1026 ../client/gdaemonfile.c:1085
+#: ../client/gdaemonfile.c:1147 ../client/gdaemonfile.c:2132
+#: ../client/gdaemonfile.c:2220 ../client/gdaemonfile.c:2489
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:977 ../client/gdaemonfile.c:1036
+#: ../client/gdaemonfile.c:1095 ../client/gdaemonfile.c:1157
+#: ../client/gdaemonfile.c:2090
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1209 ../client/gdaemonfile.c:1226
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1505
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1549
+msgid "Could not find enclosing mount"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1579
+#, c-format
+msgid "Invalid filename %s"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1621
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2012
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2061
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:451
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1304
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:403
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../client/gdaemonfileoutputstream.c:1062
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1062
+msgid "End of stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:519
+#: ../client/gdaemonfileinputstream.c:676
+#: ../client/gdaemonfileinputstream.c:785
+#: ../client/gdaemonfileinputstream.c:1036
+#: ../client/gdaemonfileoutputstream.c:460
+#: ../client/gdaemonfileoutputstream.c:639
+#: ../client/gdaemonfileoutputstream.c:835 ../daemon/gvfsbackendobexftp.c:774
+#: ../daemon/gvfsbackendobexftp.c:795 ../daemon/gvfsbackendobexftp.c:914
+#: ../daemon/gvfsbackendobexftp.c:1051 ../daemon/gvfsbackendobexftp.c:1115
+#: ../daemon/gvfsbackendobexftp.c:1252 ../daemon/gvfsbackendobexftp.c:1279
+#: ../daemon/gvfsbackendobexftp.c:1338 ../daemon/gvfsbackendobexftp.c:1360
+#: ../daemon/gvfsbackendobexftp.c:1420 ../daemon/gvfsbackendobexftp.c:1439
+#: ../daemon/gvfsbackendsmb.c:1042 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:297
+msgid "Operation was cancelled"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1211
+#: ../client/gdaemonfileoutputstream.c:946
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1241
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:731
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:559 ../client/gvfsdaemondbus.c:946
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr ""
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Çewtî: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:313 ../daemon/gvfsbackendftp.c:899
+#: ../daemon/gvfsbackendsftp.c:1738
+#, c-format
+msgid "/ on %s"
+msgstr "/ di %s de"
+
+#: ../daemon/gvfsbackendarchive.c:489 ../daemon/gvfsbackendftp.c:1415
+#: ../daemon/gvfsbackendsftp.c:1412
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:500 ../daemon/gvfsbackendarchive.c:529
+#: ../daemon/gvfsbackenddav.c:1206 ../daemon/gvfsbackendhttp.c:273
+#: ../daemon/gvfsbackendobexftp.c:605 ../daemon/gvfsbackendobexftp.c:616
+#: ../daemon/gvfsbackendsmb.c:592
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:609 ../daemon/gvfsbackendarchive.c:659
+#: ../daemon/gvfsbackendarchive.c:688 ../daemon/gvfsbackendcdda.c:825
+#: ../daemon/gvfsbackendcomputer.c:573 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2017 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:697 ../daemon/gvfsbackendburn.c:681
+#: ../daemon/gvfsbackendcomputer.c:652 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:848 ../daemon/gvfsbackendnetwork.c:637
+#, c-format
+msgid "The file is not a directory"
+msgstr ""
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:347
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:377
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:406 ../daemon/gvfsbackendburn.c:417
+#: ../daemon/gvfsbackendburn.c:452 ../daemon/gvfsbackendburn.c:673
+#: ../daemon/gvfsbackendburn.c:720 ../daemon/gvfsbackendburn.c:746
+#: ../daemon/gvfsbackendburn.c:784
+msgid "No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:426 ../daemon/gvfsbackenddav.c:1804
+msgid "Directory not empty"
+msgstr "Peldank ne vala ye"
+
+#: ../daemon/gvfsbackendburn.c:460 ../daemon/gvfsbackendburn.c:898
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:652
+msgid "CD/DVD Creator"
+msgstr "Afirandêra CD/DVD'yan"
+
+#: ../daemon/gvfsbackendburn.c:756 ../daemon/gvfsbackendburn.c:792
+#: ../daemon/gvfsbackendburn.c:918
+msgid "File exists"
+msgstr "Pel heye"
+
+#: ../daemon/gvfsbackendburn.c:846
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:869
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:878
+msgid "Target file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:885
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:944
+msgid "Not supported"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:264 ../daemon/gvfsbackendcdda.c:335
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:279
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:289
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:297
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:298 ../daemon/gvfsbackendcdda.c:802
+#: ../hal/ghalmount.c:492 ../hal/ghalvolume.c:298 ../hal/ghalvolume.c:319
+#, c-format
+msgid "Audio Disc"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:359
+#, c-format
+msgid "File system is busy: %d open file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:549
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr ""
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:658
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:721
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:818 ../daemon/gvfsbackendgphoto2.c:1695
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:832
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:938
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:180 ../daemon/gvfsbackendcomputer.c:694
+msgid "Computer"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:467
+msgid "Filesystem"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:591 ../daemon/gvfsbackendgphoto2.c:1687
+#: ../daemon/gvfsbackendobexftp.c:760 ../daemon/gvfsbackendtrash.c:637
+msgid "Can't open directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:595 ../daemon/gvfsbackendcomputer.c:733
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:781
+#, c-format
+msgid "Internal error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:813 ../daemon/gvfsbackendcomputer.c:930
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:825
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:882 ../daemon/gvfsbackendcomputer.c:973
+#: ../daemon/gvfsbackendcomputer.c:1073
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:988
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1104
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:269 ../daemon/gvfsbackenddav.c:1289
+#: ../daemon/gvfsbackendhttp.c:220
+#, c-format
+msgid "HTTP Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:285
+msgid "Could not parse response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:294
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:301
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:944 ../daemon/gvfsbackenddav.c:1421
+#, c-format
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1087
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1089
+#, c-format
+msgid "Enter password for %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1092
+msgid "Please enter proxy password"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1293 ../daemon/gvfsbackenddav.c:1297
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1319
+#, c-format
+msgid "WebDAV on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1377 ../daemon/gvfsbackenddav.c:1448
+msgid "Could not create request"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1511 ../daemon/gvfsbackenddav.c:1764
+#: ../daemon/gvfsbackendftp.c:1617 ../daemon/gvfsbackendftp.c:2281
+#: ../daemon/gvfsbackendsmb.c:1778
+#, c-format
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1584 ../daemon/gvfsbackendsftp.c:2664
+#: ../daemon/gvfsbackendsmb.c:1010
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1615 ../daemon/gvfsbackendsmb.c:1048
+#: ../daemon/gvfsbackendsmb.c:1795
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:225
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:229
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:233
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:237
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "File unavailable"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Operation failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:253
+msgid "No space left on server"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:261 ../daemon/gvfsbackendsftp.c:3686
+msgid "Operation unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:265 ../daemon/gvfsbackendsftp.c:259
+msgid "Permission denied"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:269
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:2127
+#, c-format
+msgid "Invalid filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:277 ../daemon/gvfsbackendftp.c:351
+#: ../daemon/gvfsbackendftp.c:380 ../daemon/gvfsbackendftp.c:399
+#: ../daemon/gvfsbackendftp.c:412 ../daemon/gvfsbackendftp.c:753
+#, c-format
+msgid "Invalid reply"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:519
+#, c-format
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:613 ../daemon/gvfsbackendftp.c:773
+#, c-format
+msgid "Could not connect to host"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1273
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1298 ../daemon/gvfsbackendsftp.c:835
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1377
+#, c-format
+msgid "ftp on %s"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1381
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1669 ../daemon/gvfsbackendftp.c:2242
+msgid "backups not supported yet"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1746
+#, c-format
+msgid "filename too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:2261
+#, c-format
+msgid "Invalid destination filename"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:697
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr ""
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:843 ../hal/ghalvolume.c:398
+#, c-format
+msgid "%s Camera"
+msgstr ""
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:846 ../hal/ghalvolume.c:393
+#, c-format
+msgid "%s Audio Player"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../hal/ghalvolume.c:407
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:857 ../hal/ghalvolume.c:405
+msgid "Audio Player"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1539
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:216
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:534 ../daemon/gvfsbackendsftp.c:1726
+#: ../daemon/gvfsbackendsmb.c:1275 ../daemon/gvfsbackendtrash.c:962
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr ""
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr ""
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Torê Windowsê"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr ""
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:444 ../daemon/gvfsbackendsmb.c:510
+#: ../daemon/gvfsbackendsmb.c:1268
+#, c-format
+msgid "%s on %s"
+msgstr "%s di %s de"
+
+#: ../daemon/gvfsbackendsftp.c:251
+msgid "ssh program unexpectedly exited"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:266
+msgid "Hostname not known"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:273
+msgid "No route to host"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:280
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:287
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:370
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:386
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:489 ../daemon/gvfsbackendsftp.c:741
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:819
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:821
+msgid "Enter password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:882
+msgid "Can't send password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:890
+msgid "Log In Anyway"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:890
+msgid "Cancel Login"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:900
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:920
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:940
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1331 ../daemon/gvfsbackendsftp.c:1354
+msgid "Protocol error"
+msgstr ""
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1378
+#, c-format
+msgid "sftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1402
+msgid "Unable to find supported ssh command"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1802
+msgid "File is directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1811
+msgid "Failure"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1876 ../daemon/gvfsbackendsftp.c:1938
+#: ../daemon/gvfsbackendsftp.c:1949 ../daemon/gvfsbackendsftp.c:2007
+#: ../daemon/gvfsbackendsftp.c:2097 ../daemon/gvfsbackendsftp.c:2126
+#: ../daemon/gvfsbackendsftp.c:2174 ../daemon/gvfsbackendsftp.c:2253
+#: ../daemon/gvfsbackendsftp.c:2364 ../daemon/gvfsbackendsftp.c:2405
+#: ../daemon/gvfsbackendsftp.c:2457 ../daemon/gvfsbackendsftp.c:2528
+#: ../daemon/gvfsbackendsftp.c:2548 ../daemon/gvfsbackendsftp.c:2702
+#: ../daemon/gvfsbackendsftp.c:2728 ../daemon/gvfsbackendsftp.c:2785
+#: ../daemon/gvfsbackendsftp.c:2844 ../daemon/gvfsbackendsftp.c:3124
+#: ../daemon/gvfsbackendsftp.c:3253 ../daemon/gvfsbackendsftp.c:3286
+#: ../daemon/gvfsbackendsftp.c:3387 ../daemon/gvfsbackendsftp.c:3428
+#: ../daemon/gvfsbackendsftp.c:3484 ../daemon/gvfsbackendsftp.c:3520
+#: ../daemon/gvfsbackendsftp.c:3554 ../daemon/gvfsbackendsftp.c:3569
+#: ../daemon/gvfsbackendsftp.c:3588 ../daemon/gvfsbackendsftp.c:3666
+msgid "Invalid reply received"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2195
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2610
+msgid "Unable to create temporary file"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:215
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:468 ../daemon/gvfsbackendsmb.c:502
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr ""
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:558
+msgid "Failed to mount Windows share"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:688 ../daemon/gvfsbackendsmb.c:1147
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1211
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1669
+#, c-format
+msgid "Error deleting file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1743
+#, c-format
+msgid "Error moving file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1767
+msgid "Can't move directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1815
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1839
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1902
+msgid "Windows Shares Filesystem Service"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr ""
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:600 ../daemon/gvfsbackendtrash.c:1190
+msgid "Trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:972
+#, c-format
+msgid "%s (in trash)"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1291
+msgid "Can't delete trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1638 ../daemon/gvfsbackendtrash.c:1713
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr ""
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr ""
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:119
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:169 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr ""
+
+#: ../daemon/main.c:47
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:48
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:60
+msgid "GVFS Daemon"
+msgstr "Daemon a GVFS"
+
+#: ../daemon/main.c:63
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:78
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:80 ../programs/gvfs-cat.c:165 ../programs/gvfs-cat.c:178
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:388 ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:133 ../programs/gvfs-open.c:146
+#: ../programs/gvfs-save.c:165 ../programs/gvfs-tree.c:253
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+
+#: ../daemon/mount.c:432
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:731
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:776
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:781
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:944
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:952
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../hal/ghaldrive.c:144
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../hal/ghaldrive.c:146
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../hal/ghaldrive.c:148
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../hal/ghaldrive.c:152
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../hal/ghaldrive.c:154
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../hal/ghaldrive.c:156
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../hal/ghaldrive.c:158
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../hal/ghaldrive.c:160
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../hal/ghaldrive.c:162
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../hal/ghaldrive.c:165
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../hal/ghaldrive.c:168
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../hal/ghaldrive.c:170
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../hal/ghaldrive.c:172
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../hal/ghaldrive.c:174
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../hal/ghaldrive.c:176
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../hal/ghaldrive.c:178
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../hal/ghaldrive.c:180
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../hal/ghaldrive.c:186
+#, c-format
+msgid "%s/%s Drive"
+msgstr ""
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../hal/ghaldrive.c:192
+#, c-format
+msgid "%s Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:196
+msgid "Floppy Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:202
+msgid "Software RAID Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:204
+msgid "USB Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:206
+msgid "ATA Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:208
+msgid "SCSI Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:210
+msgid "FireWire Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:214
+msgid "Tape Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:216
+msgid "CompactFlash Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:218
+msgid "MemoryStick Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:220
+msgid "SmartMedia Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:222
+msgid "SD/MMC Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:224
+msgid "Zip Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:226
+msgid "Jaz Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:228
+msgid "Thumb Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:231
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../hal/ghaldrive.c:730
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../hal/ghalmount.c:166 ../hal/ghalvolume.c:155
+msgid "CD-ROM Disc"
+msgstr "Dîska CD-ROM"
+
+#: ../hal/ghalmount.c:166 ../hal/ghalvolume.c:155
+msgid "Blank CD-ROM Disc"
+msgstr "Dîska CD-ROM a Vala"
+
+#: ../hal/ghalmount.c:167 ../hal/ghalvolume.c:156
+msgid "CD-R Disc"
+msgstr "Dîska CD-R"
+
+#: ../hal/ghalmount.c:167 ../hal/ghalvolume.c:156
+msgid "Blank CD-R Disc"
+msgstr "Dîska CD-R a Vala"
+
+#: ../hal/ghalmount.c:168 ../hal/ghalvolume.c:157
+msgid "CD-RW Disc"
+msgstr "Dîska CD-RW"
+
+#: ../hal/ghalmount.c:168 ../hal/ghalvolume.c:157
+msgid "Blank CD-RW Disc"
+msgstr "Dîska CD-RW a Vala"
+
+#: ../hal/ghalmount.c:169 ../hal/ghalmount.c:171 ../hal/ghalvolume.c:158
+#: ../hal/ghalvolume.c:160
+msgid "DVD-ROM Disc"
+msgstr "Dîska DVD-ROM"
+
+#: ../hal/ghalmount.c:169 ../hal/ghalmount.c:171 ../hal/ghalvolume.c:158
+#: ../hal/ghalvolume.c:160
+msgid "Blank DVD-ROM Disc"
+msgstr "Dîska DVD-ROM a Vala"
+
+#: ../hal/ghalmount.c:170 ../hal/ghalvolume.c:159
+msgid "DVD-RAM Disc"
+msgstr "Dîska DVD-RAM"
+
+#: ../hal/ghalmount.c:170 ../hal/ghalvolume.c:159
+msgid "Blank DVD-RAM Disc"
+msgstr "Dîska DVD-RAM a Vala"
+
+#: ../hal/ghalmount.c:172 ../hal/ghalvolume.c:161
+msgid "DVD-RW Disc"
+msgstr "Dîska DVD-RW"
+
+#: ../hal/ghalmount.c:172 ../hal/ghalvolume.c:161
+msgid "Blank DVD-RW Disc"
+msgstr "Dîska DVD-RW a Vala"
+
+#: ../hal/ghalmount.c:173 ../hal/ghalvolume.c:162
+msgid "DVD+R Disc"
+msgstr "Dîska DVD+R"
+
+#: ../hal/ghalmount.c:173 ../hal/ghalvolume.c:162
+msgid "Blank DVD+R Disc"
+msgstr "Dîska DVD+R a Vala"
+
+#: ../hal/ghalmount.c:174 ../hal/ghalvolume.c:163
+msgid "DVD+RW Disc"
+msgstr "Dîska DVD+RW"
+
+#: ../hal/ghalmount.c:174 ../hal/ghalvolume.c:163
+msgid "Blank DVD+RW Disc"
+msgstr "Dîska DVD+RW a Vala"
+
+#: ../hal/ghalmount.c:175 ../hal/ghalvolume.c:164
+msgid "DVD+R DL Disc"
+msgstr "Dîska DVD+R DL"
+
+#: ../hal/ghalmount.c:175 ../hal/ghalvolume.c:164
+msgid "Blank DVD+R DL Disc"
+msgstr "Dîska DVD+R DL a Vala"
+
+#: ../hal/ghalmount.c:176 ../hal/ghalvolume.c:165
+msgid "Blu-Ray Disc"
+msgstr "Dîska Blu-Ray"
+
+#: ../hal/ghalmount.c:176 ../hal/ghalvolume.c:165
+msgid "Blank Blu-Ray Disc"
+msgstr "Dîska Blu-Ray a Vala"
+
+#: ../hal/ghalmount.c:177 ../hal/ghalvolume.c:166
+msgid "Blu-Ray R Disc"
+msgstr "Dîska Blu-Ray R"
+
+#: ../hal/ghalmount.c:177 ../hal/ghalvolume.c:166
+msgid "Blank Blu-Ray R Disc"
+msgstr "Dîska Blu-Ray R a Vala"
+
+#: ../hal/ghalmount.c:178 ../hal/ghalvolume.c:167
+msgid "Blu-Ray RW Disc"
+msgstr "Dîska Blu-Ray RW"
+
+#: ../hal/ghalmount.c:178 ../hal/ghalvolume.c:167
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Dîska Blu-Ray RW a Vala"
+
+#: ../hal/ghalmount.c:179 ../hal/ghalvolume.c:168
+msgid "HD DVD Disc"
+msgstr "Dîska HD DVD"
+
+#: ../hal/ghalmount.c:179 ../hal/ghalvolume.c:168
+msgid "Blank HD DVD Disc"
+msgstr "Dîska HD DVD a Vala"
+
+#: ../hal/ghalmount.c:180 ../hal/ghalvolume.c:169
+msgid "HD DVD-R Disc"
+msgstr "Dîska HD DVD-R"
+
+#: ../hal/ghalmount.c:180 ../hal/ghalvolume.c:169
+msgid "Blank HD DVD-R Disc"
+msgstr "Dîska HD DVD-R a Vala"
+
+#: ../hal/ghalmount.c:181 ../hal/ghalvolume.c:170
+msgid "HD DVD-RW Disc"
+msgstr "Dîska HD DVD-RW"
+
+#: ../hal/ghalmount.c:181 ../hal/ghalvolume.c:170
+msgid "Blank HD DVD-RW Disc"
+msgstr "Dîska HD DVD-RW a Vala"
+
+#: ../hal/ghalmount.c:182 ../hal/ghalvolume.c:171
+msgid "MO Disc"
+msgstr "Dîska MO"
+
+#: ../hal/ghalmount.c:182 ../hal/ghalvolume.c:171
+msgid "Blank MO Disc"
+msgstr "Dîska MO ya Vala"
+
+#: ../hal/ghalmount.c:183 ../hal/ghalvolume.c:172
+msgid "Disc"
+msgstr "Dîsk"
+
+#: ../hal/ghalmount.c:183 ../hal/ghalvolume.c:172
+msgid "Blank Disc"
+msgstr "Dîska Vala"
+
+#: ../hal/ghalmount.c:368
+#, c-format
+msgid "%.1f kB Media"
+msgstr ""
+
+#: ../hal/ghalmount.c:373
+#, c-format
+msgid "%.1f MB Media"
+msgstr ""
+
+#: ../hal/ghalmount.c:378
+#, c-format
+msgid "%.1f GB Media"
+msgstr ""
+
+#: ../hal/ghalmount.c:490 ../hal/ghalvolume.c:317
+msgid "Mixed Audio/Data Disc"
+msgstr ""
+
+#: ../hal/ghalvolume.c:206
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../hal/ghalvolume.c:211
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../hal/ghalvolume.c:216
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:305
+#, c-format
+msgid "%s Encrypted Data"
+msgstr ""
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:328
+#, c-format
+msgid "%s Media"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:59
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:82
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:94
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:112
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-cat.c:138
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:143
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:150
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:176 ../programs/gvfs-open.c:144
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:58
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:85
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:115
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:119
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
diff --git a/trunk/po/lt.po b/trunk/po/lt.po
new file mode 100644
index 00000000..db00cdd0
--- /dev/null
+++ b/trunk/po/lt.po
@@ -0,0 +1,1675 @@
+# translation of gvfs to Lithuanian
+# Copyright (C) 2008 Gintautas Miliauskas
+# This file is distributed under the same license as the gvfs package.
+#
+# Gintautas Miliauskas <gintas@akl.lt>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-08 01:35+0200\n"
+"PO-Revision-Date: 2009-03-08 01:35+0200\n"
+"Last-Translator: Gintautas Miliauskas <gintas@akl.lt>\n"
+"Language-Team: Lithuanian <gnome-lt@lists.akl.lt>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%"
+"100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operacija nepalaikoma, failai skirtinguose prijungimo taškuose"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Nepavyko gauti srauto failo deskriptoriaus"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Nepavyko gauti srauto failo deskriptoriaus"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Netaisyklinga kvietimo grąžinta reikšmė"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info grąžino netaisyklingą reikšmę"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nepavyko rasti tėvinio prijungimo taško"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Netaisyklingas failo vardas „%s“"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file grąžino netaisyklingą reikšmę"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:298
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "Operacija nutraukta"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Klaida srauto protokole: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Srauto pabaiga"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "Pozicijos keitimas sraute nepalaikomas"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Klaida gaunant prijungimo taško informaciją: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Klaida jungiantis prie tarnybos: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read grąžino netaisyklingą reikšmę"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Klaida kuriant lizdą: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Klaida jungiantis prie lizdo: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Netaisyklingas failo informacijos formatas"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Netaisyklingas atributo informacijos sąrašo turinys"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Klaida inicializuojant Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Klaida kuriant Avahi „resolver“ tarnybą: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Klaida ieškant „%s“ tarnybos „%s“ srityje „%s“"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Klaida ieškant „%s“ tarnybos „%s“ srityje „%s“. Trūksta vieno ar daugiau TXT "
+"įrašų. Reikalingi raktai: „%s“."
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Baigėsi laikas ieškant „%s“ tarnybos „%s“ srityje „%s“"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Netaisyklingas dns-sd koduotas tripletas „%s“"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Negalima apdoroti GVfsIcon kodavimo versijos %d"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Netaisyklingi duomenys GVfsIcon"
+
+#: ../daemon/daemon-main.c:76 ../daemon/daemon-main.c:226
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Klaida jungiantis prie D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:91
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s failų sistemos tarnyba"
+
+#: ../daemon/daemon-main.c:110
+#, c-format
+msgid "Error: %s"
+msgstr "Klaida: %s"
+
+#: ../daemon/daemon-main.c:151
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Naudojimas: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:175 ../daemon/daemon-main.c:193
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Naudojimas: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:191
+#, c-format
+msgid "No mount type specified"
+msgstr "Nenurodytas prijungimo taško tipas"
+
+#: ../daemon/daemon-main.c:261
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "prijungimo taškas %s jau aktyvus"
+
+#: ../daemon/daemon-main.c:272
+msgid "error starting mount daemon"
+msgstr "klaida paleidžiant prijungimo taškų tarnybą"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1912
+#, c-format
+msgid "/ on %s"
+msgstr "/ kompiuteryje %s"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "No hostname specified"
+msgstr "Nenurodytas kompiuterio vardas"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Netaisyklinga prijungimo taško specifikacija"
+
+#: ../daemon/gvfsbackendarchive.c:639 ../daemon/gvfsbackendarchive.c:689
+#: ../daemon/gvfsbackendarchive.c:718 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2264 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Failas neegzistuoja"
+
+#: ../daemon/gvfsbackendarchive.c:727 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Failas nėra aplankas"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Rašyti"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nepavyko sukurti laikino aplanko"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:717 ../daemon/gvfsbackendburn.c:743
+#: ../daemon/gvfsbackendburn.c:781 ../daemon/gvfsbackendburn.c:972
+#: ../daemon/gvfsbackendburn.c:1008 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Tokio failo ar aplanko nėra"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Aplankas netuščias"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:904
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Negalima kopijuoti failo ant katalogo"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD kūrimas"
+
+#: ../daemon/gvfsbackendburn.c:753 ../daemon/gvfsbackendburn.c:789
+#: ../daemon/gvfsbackendburn.c:924 ../daemon/gvfsbackendburn.c:986
+#: ../daemon/gvfsbackendburn.c:990 ../daemon/gvfsbackendburn.c:1000
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Failas egzistuoja"
+
+#: ../daemon/gvfsbackendburn.c:828 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operacija nepalaikoma posistemės"
+
+#: ../daemon/gvfsbackendburn.c:853
+msgid "No such file or directory in target path"
+msgstr "Paskirties kelyje nėra tokio failo ar aplanko"
+
+#: ../daemon/gvfsbackendburn.c:876 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Negalima kopijuoti aplanko ant aplanko"
+
+#: ../daemon/gvfsbackendburn.c:885 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Paskirties failas egzistuoja"
+
+#: ../daemon/gvfsbackendburn.c:892 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Negalima rekursyviai kopijuoti aplanko"
+
+#: ../daemon/gvfsbackendburn.c:950 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Nepalaikoma"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Nepavyko prisijungti prie sisteminės magistralės"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Nepavyko sukurti libhal konteksto"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Nepavyko inicializuoti libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nenurodytas įrenginys"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Nepavyko rasti įrenginio %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Įrenginyje %s nėra audio failų"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda prijungimo taškas %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325 ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio diskas"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Failų sistema užimta: %d atvertas failas"
+msgstr[1] "Failų sistema užimta: %d atverti failai"
+msgstr[2] "Failų sistema užimta: %d atvertų failų"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nėra failo %s įrenginyje %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "„paranoia“ klaida įrenginyje %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Klaida keičiant poziciją sraute įrenginyje %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Nėra tokio failo"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Failas neegzistuoja arba nėra audio takelis"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Audio CD failų sistemos tarnyba"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Kompiuteris"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Failų sistema"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:691
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Nepavyko atverti aplanko"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Nepavyko atverti prijungiamo failo"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1055
+#, c-format
+msgid "Internal error: %s"
+msgstr "Vidinė klaida: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Nepavyko prijungti failo"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Įrenginyje nėra laikmenos"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ne prijungiamas failas"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Nepavyko atjungti failo"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Nepavyko išstumti failo"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP klaida: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Neavyko apdoroti atsakymo"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Tuščias atsakymas"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Netikėtas atsakymas iš serverio"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Atsakymas nekorektiškas"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV viešinys"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Įveskite %s slaptažodį"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Įveskite tarpinio serverio slaptažodį"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Ne WebDAV viešinys"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Nepavyko sukurti užklausos"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528 ../daemon/gvfsbackendsftp.c:3783
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Paskirties failas jau egzistuoja"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2950
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "Failas modifikuotas išorinės programos"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "Atsarginio failo kūrimas nesėkmingas"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Vietinis tinklas"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Nepavyko stebėti failo ar aplanko."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Tinklas"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Paskyros nepalaikomos"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Kompiuteris uždarė prisijungimą"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Nepavyko atverti duomenų prisijungimo. Gal tai draudžia Jūsų ugniasienė?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Duomenų prisijungimas užvertas"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Operacija nesėkminga"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Serveryje neliko laisvos vietos"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4094
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Operacija nepalaikoma"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Leidimas neduotas"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Puslapio tipas nežinomas"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "Netaisyklingas failo vardas"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "Netaisyklingas atsakymas"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "nutrauktas perdavimas"
+
+#: ../daemon/gvfsbackendftp.c:713 ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "Nepavyko prisijungti prie kompiuterio"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Įveskite FTP slaptažodį naudotojui %s kompiuteryje %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Įveskite FTP slaptažodį %s"
+
+#: ../daemon/gvfsbackendftp.c:1525 ../daemon/gvfsbackendsftp.c:877
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Slaptažodžio dialogas atmestas"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "FTP %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "FTP vardu %s kompiuteryje %s"
+
+#: ../daemon/gvfsbackendftp.c:1692 ../daemon/gvfsbackendsftp.c:1976
+#: ../daemon/gvfsbackendsftp.c:3774
+msgid "File is directory"
+msgstr "Failas yra aplankas"
+
+#: ../daemon/gvfsbackendftp.c:1914 ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2811
+msgid "backups not supported yet"
+msgstr "atsarginės kopijos dar nepalaikomos"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "failo vardas per ilgas"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "Netaisyklingas paskirties failo vardas"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Aplankas ar failas jau egzistuoja"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Tokio failo ar aplanko nėra"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Netaisyklingas failo vardas"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nepalaikoma"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Skaitmeninė kamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s audio grotuvas"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Audio grotuvas"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Nenurodytas įrenginys"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Nepavyko sukurti gphoto2 konteksto"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Klaida kuriant kamerą"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Klaida įkeliant įrenginio informaciją"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Klaida ieškant įrenginio informacijos"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Klaida gaunant įrenginio informaciją"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Klaida nustatant kameros komunikacijos prievadą"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Klaida inicializuojant kamerą"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 prijungimo taškas %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Nenurodyta jokia kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Klaida kuriant failo objektą"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Klaida gaunant failą"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Klaida gaunant duomenis iš failo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Netaisyklingas piktogramos identifikatorius „%s“"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Klaida keičiant poziciją sraute kameroje %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ne aplankas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Failas gauti aplankų sąrašo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Nepavyko gauti failų sąrašo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Klaida kuriant aplanką"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Vardas jau egzistuoja"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Nauajs failo vardas per ilgas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Klaida pervadinant aplanką"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Klaida pervadinant failą"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Aplankas „%s“ netuščias"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Klaida trinant aplanką"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Klaida trinant failą"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Nepavyko rašyti į aplanką"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Nepavyko išskirti naujo failo, į kurį rašyti"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Nepavyko skaityti failo, į kurį rašyti"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Nepavyko gauti duomenų iš failo, į kurį rašyti"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Klaida rašant failą"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Nepalaikoma (ne tas pats aplankas)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nepalaikoma (šaltinis – aplankas, paskirtis – aplankas)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nepalaikoma (šaltinis – aplankas, paskirtis – egzistuojantis failas)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nepalaikoma (šaltinis – failas, paskirtis – aplankas)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP kliento klaida: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1900
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (netaisyklinga koduotė)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Aplankų pranešimas nepalaikomas"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows tinklas"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Tinklo vietų stebyklė"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s kompiuteryje %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Nėra USB palaikymo. Susisiekite su programinės įrangos gamintoju"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Prisijungimas prie prietaiso prarastas"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Reikia atnaujinti prietaiso programinę įrangą"
+
+#: ../daemon/gvfsbackendsftp.c:291
+msgid "ssh program unexpectedly exited"
+msgstr "ssh programa netikėtai užsidarė"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Kompiuterio vardas nežinomas"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "Nėra maršruto iki kompiuterio"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "Serveris atmetė prisijungimą"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Kompiuterio rakto verifikavimas nesėkmingas"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "Nepavyko paleisti ssh programos"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Nepavyko paleisti ssh programos: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:783
+msgid "Timed out when logging in"
+msgstr "Baigėsi prisijungimo laiko limitas"
+
+#: ../daemon/gvfsbackendsftp.c:861
+msgid "Enter passphrase for key"
+msgstr "Įveskite slaptą frazę"
+
+#: ../daemon/gvfsbackendsftp.c:863
+msgid "Enter password"
+msgstr "Įveskite slaptažodį"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send password"
+msgstr "Nepavyko išsiųsti slaptažodžio"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Log In Anyway"
+msgstr "Vis vien prisijungti"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Cancel Login"
+msgstr "Nutraukti prisijungimą"
+
+#: ../daemon/gvfsbackendsftp.c:957
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Nutolusio kompiuterio (%s) tapatybė nežinoma.\n"
+"Tai atsitinka, kai jungiatės prie kompiuterio pirmą kartą.\n"
+"\n"
+"Kompiuterio atsiųsta tapatybė yra %s. Jei norite būti visiškai tikri, kad "
+"saugu tęsti, susisiekite su sistemos administratoriumi."
+
+#: ../daemon/gvfsbackendsftp.c:977
+msgid "Login dialog cancelled"
+msgstr "Prisijungimo dialogas atmestas"
+
+#: ../daemon/gvfsbackendsftp.c:997
+msgid "Can't send host identity confirmation"
+msgstr "Nepavyko nusiųsti kompiuterio tapatybės patvirtinimo"
+
+#: ../daemon/gvfsbackendsftp.c:1490 ../daemon/gvfsbackendsftp.c:1513
+msgid "Protocol error"
+msgstr "Protokolo klaida"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1538
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "SFTP (%s) kompiuteryje %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1541
+#, c-format
+msgid "sftp on %s"
+msgstr "SFTP kompiuteryje %s"
+
+#: ../daemon/gvfsbackendsftp.c:1567
+msgid "Unable to find supported ssh command"
+msgstr "Nepavyko rasti palaikomos ssh komandos"
+
+#: ../daemon/gvfsbackendsftp.c:1985
+msgid "Failure"
+msgstr "Nesėkmė"
+
+#: ../daemon/gvfsbackendsftp.c:2041 ../daemon/gvfsbackendsftp.c:2120
+#: ../daemon/gvfsbackendsftp.c:2131 ../daemon/gvfsbackendsftp.c:2187
+#: ../daemon/gvfsbackendsftp.c:2273 ../daemon/gvfsbackendsftp.c:2323
+#: ../daemon/gvfsbackendsftp.c:2369 ../daemon/gvfsbackendsftp.c:2444
+#: ../daemon/gvfsbackendsftp.c:2551 ../daemon/gvfsbackendsftp.c:2591
+#: ../daemon/gvfsbackendsftp.c:2641 ../daemon/gvfsbackendsftp.c:2713
+#: ../daemon/gvfsbackendsftp.c:2725 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2825 ../daemon/gvfsbackendsftp.c:3002
+#: ../daemon/gvfsbackendsftp.c:3027 ../daemon/gvfsbackendsftp.c:3082
+#: ../daemon/gvfsbackendsftp.c:3139 ../daemon/gvfsbackendsftp.c:3410
+#: ../daemon/gvfsbackendsftp.c:3477 ../daemon/gvfsbackendsftp.c:3612
+#: ../daemon/gvfsbackendsftp.c:3672 ../daemon/gvfsbackendsftp.c:3707
+#: ../daemon/gvfsbackendsftp.c:3735 ../daemon/gvfsbackendsftp.c:3843
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3933
+#: ../daemon/gvfsbackendsftp.c:3967 ../daemon/gvfsbackendsftp.c:3982
+#: ../daemon/gvfsbackendsftp.c:3997 ../daemon/gvfsbackendsftp.c:4075
+msgid "Invalid reply received"
+msgstr "Gautas netaisyklingas atsakymas"
+
+#: ../daemon/gvfsbackendsftp.c:2093
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Netinkamas icon_id „%s“ (OpenIconForRead)"
+
+#: ../daemon/gvfsbackendsftp.c:2389
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Klaida kuriant atsarginės kopijos failą: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2887
+msgid "Unable to create temporary file"
+msgstr "Nepavyko sukurti laikino failo"
+
+#: ../daemon/gvfsbackendsftp.c:3769 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "Negalima perkelti aplanko ant aplanko"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Viešiniui %s kompiuteryje %s reikalingas slaptažodis"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Vidinė klaida (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Nepavyko prijungti Windows viešinio"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Nepalaikomas pozicijos keitimo tipas"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Atsarginės kopijos kūrimas nesėkmingas: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Klaida trinant failą: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Klaida perkeliant failą: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Klaida šalinant paskirties failą: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "Negalima rekursyviai perkelti aplanko"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows viešinių failų sistemos tarnyba"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Kompiuteriui %s reikalingas slaptažodis"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows viešiniai %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Nepavyko iš serverio gauti viešinių sąrašo"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Šis failas nėra prijungiamas"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ne paprastas failas"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows tinklo failų sistemos tarnyba"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Šiukšlių aplankas negali būti ištrintas"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Šiukšlių aplanko turinys negali būti keičiamas"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Šiukšlės"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Klaidingas posistemės tipas"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Klaida siunčiant fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Simbolinės nuorodos nepalaikomos posistemės"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Netaisyklingas D-Bus pranešimas"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Pakeisti seną tarnybą."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Nepaleisti fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS tarnyba"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Pagrindinė GVFS tarnyba"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Pabandykite „%s --help“, jei norite gauti daugiau informacijos."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Netaisyklingi argumentai iš sukurto antrinio proceso"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatinis prijungimas nesėkmingas: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Nurodyta vieta nėra prijungimo taškas"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Nurodyta vieta nepalaikoma"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Vieta jau prijungta"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Vieta neprijungiama"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tuščias CD-ROM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tuščias CD-R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tuščias CD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tuščias DVD-ROM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tuščias DVD-RAM diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tuščias DVD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tuščias DVD+R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tuščias DVD+RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tuščias DVD+R DL diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tuščias Blu-Ray diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tuščias Blu-Ray R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tuščias Blu-Ray RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tuščias HD DVD diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tuščias HD DVD-R diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tuščias HD DVD-RW diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tuščias MO diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Diskas"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tuščias diskas"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s įrenginys"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "%s įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "Diskelių įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "Programinis RAID įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "USB diskas"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "ATA diskas"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "SCSI diskas"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "FireWire diskas"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "Kasečių įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "CompactFlash įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "MemoryStick įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "SmartMedia įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "SD/MMC įrenginys"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Zip diskas"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Jaz diskas"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "Flash laikmena"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "Duomenų laikmena"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Nepavyko išstumti medijos; vienas ar daugiau skirsnių užimti."
+
+#: ../monitor/hal/ghalmount.c:159 ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:164 ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:169 ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:323 ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "Mišrus audio/duomenų diskas"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336 ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "%s laikmena"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s šifruoti duomenys"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: klaida atveriant failą: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, klaida rašant į standartinį išvedimą"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: klaida skaitant: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:klaida užveriant: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "VIETA... – sujungti VIETAS ir išvesti į standartinį išvedimą"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Sujungti failus nurodytose vietose ir išvesti į standartinį išvedimą. Veikia "
+"kaip tradicinė „cat“ programa, tačiau palaiko gvfs vietas, o ne tik "
+"vietinius failus. Pavyzdžiui, galite nurodyti „smb://serveris/resursas/"
+"failas.txt“."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Pastaba: filtruokite per cat, jei reikia jo formatavimo funkcionalumo (-n, -"
+"T ar kt.)."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: trūkstamos vietos"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: klaida atveriant vietą: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: klaida paleidžiant programą: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "FAILAI... – atverti FAILUS su registruota programa."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Atveria failus su numatytąja programa, registruota atitinkamiems failų "
+"tipams."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "Informacijos užklausimo operacija nepalaikoma"
+
+#~ msgid "Query info not supported on stream"
+#~ msgstr "Informacijos užklausimas sraute nepalaikomas"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (šiukšlėse)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Negalima ištrinti šiukšlių"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Šiukšlių aplanko pranešimai nepalaikomi"
+
+#~ msgid "File unavailable"
+#~ msgstr "Failas neprieinamas"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB laikmena"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB laikmena"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB laikmena"
diff --git a/trunk/po/lv.po b/trunk/po/lv.po
new file mode 100644
index 00000000..4b0f9dcd
--- /dev/null
+++ b/trunk/po/lv.po
@@ -0,0 +1,1603 @@
+# Latvian translation for gvfs
+# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008
+# This file is distributed under the same license as the gvfs package.
+#
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2008.
+# Raivis Dejus <orvils@gmail.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
+"cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2008-12-30 21:27+0000\n"
+"PO-Revision-Date: 2009-01-04 17:38+0200\n"
+"Last-Translator: Raivis Dejus <orvils@gmail.com>\n"
+"Language-Team: en_US <locale@laka.lv>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
+"X-Launchpad-Export-Date: 2009-01-04 12:48+0000\n"
+"X-Generator: Lokalize 0.2\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Darbība nav atbalstīta, faili atrodas dažādos montējumos"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Nederīga get_info atgrieztā vērtība"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Nederīga query_info atgrieztā vērtība"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Nevar iegūt straumes faila aprakstītāju"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Nederīga open atgrieztā vērtība"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Netika iegūts straumes faila aprakstītājs"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Nederīga call atgrieztā vērtība"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Nederīga get_filesystem_info atgrieztā vērtība"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nevarēja atrast ietverošo montējumu"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nederīgs faila nosaukums %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Nederīga query_filesystem_info atgrieztā vērtība"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:741
+#: ../daemon/gvfsbackendobexftp.c:762 ../daemon/gvfsbackendobexftp.c:881
+#: ../daemon/gvfsbackendobexftp.c:1018 ../daemon/gvfsbackendobexftp.c:1082
+#: ../daemon/gvfsbackendobexftp.c:1219 ../daemon/gvfsbackendobexftp.c:1246
+#: ../daemon/gvfsbackendobexftp.c:1305 ../daemon/gvfsbackendobexftp.c:1327
+#: ../daemon/gvfsbackendobexftp.c:1387 ../daemon/gvfsbackendobexftp.c:1406
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Darbība tika atcelta"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Kļūda plūsmas protokolā: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Plūsmas beigas"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Meklešana plūsmā nav atbalstīta"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Nederīga open_icon_for_read atgrieztā vērtība"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr ""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr ""
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr ""
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Kļūda: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:561 ../daemon/gvfsbackendobexftp.c:572
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1111
+#, c-format
+msgid "File doesn't exist"
+msgstr "Fails neeksistē"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:440
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "Fails nav direktorija"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Neizdevās izveidot pagaidu direktoriju"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:214
+#, c-format
+msgid "No such file or directory"
+msgstr "Nav tāda faila vai direktorijas"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Direktorija nav tukša"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD veidotājs"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Fails jau eksistē"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "Mērķa fails eksistē"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Nav atbalstīts"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio disks"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr ""
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Nav tāda faila"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Dators"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Failu sistēma"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:727 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:230
+#, c-format
+msgid "Can't open directory"
+msgstr "Nevar atvērt direktoriju"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Iekšēja kļūda: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP kļūda: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Tukša atbilde"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Nederīga atbilde"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Ievadiet %s paroli"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Mērķa fails jau eksistē"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr ""
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:487 ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Lokālais tīkls"
+
+#: ../daemon/gvfsbackenddnssd.c:731 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:749
+msgid "Dns-SD"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:750 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Tīkls"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Datu savienojums slēgts"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Operācija neizdevas"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Uz servera vairs nav brīvas vietas"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Neatbalstīta operācija"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Nezināms lapas tips"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nederīgs faila nosaukums"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Fails ir direktorija"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "rezerves kopijas vēl netiek atbalstītas"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "faila nosaukums par garu"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitālā fotokamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s fotokamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Fotokamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1107
+msgid "Not a directory"
+msgstr "Nav direktorija"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP klienta kļūda: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (nederīgs kodējums)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr ""
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windows tīkls"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:387 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s uz %s"
+
+#: ../daemon/gvfsbackendobexftp.c:666
+msgid "Connection to the device lost"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:1163
+msgid "Device requires a software update"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Ievadiet paroli"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Tomēr pieslēgties"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Atcelt pieslēgšanos"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokola kļūda"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "%s sftp uz %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp uz %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Nav iespējams izveidot pagaidu failu"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr ""
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1219
+msgid "Windows Network Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:344
+#, c-format
+msgid "Can't delete trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:361 ../daemon/gvfsbackendtrash.c:413
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:399
+#, c-format
+msgid "Can't pull trash"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:708 ../daemon/gvfsbackendtrash.c:816
+msgid "Trash"
+msgstr "Miskaste"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr ""
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr ""
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr ""
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr ""
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Pamēģiniet \"%s --help\", lai iegūtu vairāk informācijas."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tukšs CD-ROM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tukšs CD-R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tukšs CD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tukšs DVD-ROM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tukšs DVD-RAM disks"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tukšs DVD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tukšs DVD+R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tukšs DVD+RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Divslāņu DVD+R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tukšs divslāņu DVD+R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray disks"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tukšs Blu-Ray disks"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tukšs Blu-Ray R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tukšs Blu-Ray RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD disks"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tukšs HD DVD disks"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tukšs HD DVD-R disks"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tukšs DVD-RW disks"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO disks"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tukšs MO disks"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disks"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tukšs disks"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s dzinis"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s dzinis"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskešu dzinis"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB dzinis"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA dzinis"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI dzinis"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire dzinis"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Lenšdzinis"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash dzinis"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick dzinis"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia dzinis"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC dzinis"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip dzinis"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz dzinis"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr ""
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s nesējs"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
diff --git a/trunk/po/mk.po b/trunk/po/mk.po
new file mode 100644
index 00000000..036f59fb
--- /dev/null
+++ b/trunk/po/mk.po
@@ -0,0 +1,1556 @@
+# translation of mk.po to Macedonian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Jovan Naumovski <jovan@lugola.net>, 2008.
+# Arangel Angov <ufo@linux.net.mk>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: mk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-21 15:25+0000\n"
+"PO-Revision-Date: 2008-08-27 17:05+0200\n"
+"Last-Translator: Jovan Naumovski <jovan@lugola.net>\n"
+"Language-Team: en_US <kde-i18n-doc@lists.kde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural= n==1 || n%10==1 ? 0 : 1\n"
+"X-Generator: KAider 0.1\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr "Операцијата не е поддржана, датотеки на различни монтирања"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Вратена е невалидна вредност од get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Вратена е невалидна вредност од query_info"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "Не можев да добијам датотека со опишувач на стрим"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr "Вратена е невалидна вредност од open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr "Не добив датотека со опишувач за стрим"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Вратена е невалидна вредност од call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Вратена е невалидна вредност од get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Не можев да добијам соодветно монтирање"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Невалидно име на датотека %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Вратена е невалидна вредност од query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr "Вратена е невалидна вредност од monitor_dir"
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr "Вратена е невалидна вредност од monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Грешка во протоколот за стримување: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Крај на стрим"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Операцијата беше прекината"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Барањето не е поддржано за стримот"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Операцијата за барање на информации не е поддржана"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Барањето не е поддржано за стримот"
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Грешка при добивањето на податоци за монтирањето: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Грешка при поврзувањето со демонот: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Грешка при креирањето на сокет: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Грешка при поврзувањето со сокет: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Невалиден формат за датотеки со информации"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "Невалидна содржина за листа со атрибути на информации"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Грешка при поврзувањето со D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Сервис за датотечен систем на %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Грешка: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Употреба: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Употреба: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Не е одредена точка на монтирање"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "Точката за монтирање на %s веќе се извршува"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "грешка при стартувањето на демонот за монтирање"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ на %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Не е одредено име на хост"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1449 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr "Невалидни спецификации за монтирање"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "Датотеката не постои"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "Датотеката не е директориум"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Сними"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Не можам да креирам привремен директориум"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "No such file or directory"
+msgstr "Нема таква датотека или директориум"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2036
+msgid "Directory not empty"
+msgstr "Директориумот не е празен"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr "Не можам да ја копирам датотеката над директориумот"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Креатор на CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2763
+msgid "File exists"
+msgstr "Датотеката постои"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr "Нема таква датотека или директориум во целната патека"
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr "Не можам да го копирам директориумот над директориум"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Target file exists"
+msgstr "Целната датотека постои"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr "Не можам да го ископирам директориумот рекурзивно"
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2348
+#: ../daemon/gvfsbackendgphoto2.c:2556 ../daemon/gvfsbackendgphoto2.c:2651
+#: ../daemon/gvfsbackendgphoto2.c:2742
+msgid "Not supported"
+msgstr "Не е поддржано"
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot connect to the system bus"
+msgstr "Не можам да се поврзам со системската магистрала"
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot create libhal context"
+msgstr "Не можам да креирам содржина за libhal"
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1427
+msgid "Cannot initialize libhal"
+msgstr "Не можам да го иницијализирам libhal"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr "Не е одреден уред"
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Не можам да го пронајдам уредот %s"
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Уредот %s не содржи аудио датотеки"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda точка за монтирање на %s"
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Аудио диск"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1655
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Датотечниот систем е зафатен: %d отворена датотека"
+msgstr[1] "Датотечниот систем е зафатен: %d отворени датотеки"
+msgstr[2] "Датотечниот систем е зафатен: %d отворени датотеки"
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Ја нема датотеката %s на уредот %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Грешка од „paranoia“ на уредот %s"
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Грешка во барањето во стримот на датотеката %s"
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1711
+#, c-format
+msgid "No such file"
+msgstr "Нема таква датотека"
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Датотеката не постои или не е аудио трака"
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr "Сервис за датотечен систем на аудио CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Компјутер"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Датотечен систем"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1703
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+msgid "Can't open directory"
+msgstr "Не можам да го отворам директориумот"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "Не можам да отворам монтирачка датотека"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Внатрешна грешка: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "Не можам да ја монтирам датотеката"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "Нема медиум во уредот"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Не е монтирачка датотека"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "Не можам да ја одмонтирам датотеката"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "Не можам да ја извадам датотеката"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1516
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP грешка: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "Не можев да го парсирам одговорот"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Празен одговор"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Неочекуван одговор од серверот"
+
+#: ../daemon/gvfsbackenddav.c:1149 ../daemon/gvfsbackenddav.c:1651
+msgid "Response invalid"
+msgstr "Невалиден одговор"
+
+#: ../daemon/gvfsbackenddav.c:1292
+msgid "WebDAV share"
+msgstr "WebDAV споделување"
+
+#: ../daemon/gvfsbackenddav.c:1294
+#, c-format
+msgid "Enter password for %s"
+msgstr "Внесете лозинка за %s"
+
+#: ../daemon/gvfsbackenddav.c:1297
+msgid "Please enter proxy password"
+msgstr "Ве молам, внесете лозинка за проксито"
+
+#: ../daemon/gvfsbackenddav.c:1520 ../daemon/gvfsbackenddav.c:1524
+msgid "Not a WebDAV enabled share"
+msgstr "Не е споделување овозможено со WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1547
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV на %s"
+
+#: ../daemon/gvfsbackenddav.c:1607 ../daemon/gvfsbackenddav.c:1680
+msgid "Could not create request"
+msgstr "Не можев да креирам барање"
+
+#: ../daemon/gvfsbackenddav.c:1743 ../daemon/gvfsbackenddav.c:1996
+#: ../daemon/gvfsbackenddav.c:2107 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr "Целната датотека веќе постои"
+
+#: ../daemon/gvfsbackenddav.c:1816 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr "Датотеката беше изменета од надвор"
+
+#: ../daemon/gvfsbackenddav.c:1847 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr "Креирањето на бекап датотека не успеа"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Не можам да ја надгледувам датотеката или директориумот."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Мрежа"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "Сметки не се поддржани"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "Хостот ја затвори врската"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Не можам да отворам врска за податоци. Можеби Вашиот заштитен ѕид го "
+"спречува ова?"
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "Врската за податоци е затворена"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Операцијата не успеа"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "Нема преостанато место на серверот"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Операцијата не е поддржана"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Пристапот е одбиен"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "Типот на страницата е непознат"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Невалидно име на датотека"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Невалиден одговор"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "прекинат пренос"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "Не можам да се врзам за хостот"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Внесете лозинка за ftp на %s"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Дијалог прозорецот за лозинка беше откажан"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp на %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp како %s на %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "Датотеката е директориум"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "правењето на резерви се уште не е поддржано"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "името на датотеката е преголемо"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "Невалидно име на дестинациска датотека"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: директориумот или датотеката постои"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: нема таква датотека или директориум"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: невалидно име на датотека"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: не е поддржано"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Дигитална камера (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s камера"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s пуштач на аудио"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Пуштач на аудио"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get folder list"
+msgstr "Не успеав да земам листа на папки"
+
+#: ../daemon/gvfsbackendgphoto2.c:1442
+msgid "No device specified"
+msgstr "Не е одреден уред"
+
+#: ../daemon/gvfsbackendgphoto2.c:1459
+msgid "Cannot create gphoto2 context"
+msgstr "Не можам да креирам содржина за gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469
+msgid "Error creating camera"
+msgstr "Грешка при креирањето на камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:1482 ../daemon/gvfsbackendgphoto2.c:1492
+msgid "Error loading device information"
+msgstr "Грешка во вчитувањето на информации за уредот"
+
+#: ../daemon/gvfsbackendgphoto2.c:1504
+msgid "Error looking up device information"
+msgstr "Грешка во барањето на информации за уредот"
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error getting device information"
+msgstr "Грешка во добивањето на информации од уредот"
+
+#: ../daemon/gvfsbackendgphoto2.c:1527
+msgid "Error setting up camera communications port"
+msgstr "Грешка во поставувањето на портата за комуникација на камерата"
+
+#: ../daemon/gvfsbackendgphoto2.c:1538
+msgid "Error initializing camera"
+msgstr "Грешка во иницијализирањето на камерата"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1552
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 точка за монтирање на %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1627
+msgid "No camera specified"
+msgstr "Не е одредена камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error creating file object"
+msgstr "Грешка при креирањето на објект датотека"
+
+#: ../daemon/gvfsbackendgphoto2.c:1733
+msgid "Error getting file"
+msgstr "Грешка во добивањето на датотека"
+
+#: ../daemon/gvfsbackendgphoto2.c:1742
+msgid "Error getting data from file"
+msgstr "Грешка во добивањето на податоци од датотеката"
+
+#: ../daemon/gvfsbackendgphoto2.c:1836 ../daemon/gvfsbackendgphoto2.c:3010
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Грешка во барањето во стримот на камерата %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1975 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Не е директориум"
+
+#: ../daemon/gvfsbackendgphoto2.c:2071
+msgid "Failed to get file list"
+msgstr "Не успеав да земам листа на датотеки"
+
+#: ../daemon/gvfsbackendgphoto2.c:2360
+msgid "Error creating directory"
+msgstr "Грешка при креирањето на директориум"
+
+#: ../daemon/gvfsbackendgphoto2.c:2568
+msgid "Name already exists"
+msgstr "Името веќе постои"
+
+#: ../daemon/gvfsbackendgphoto2.c:2579 ../daemon/gvfsbackendgphoto2.c:3200
+msgid "New name too long"
+msgstr "Името е предолго"
+
+#: ../daemon/gvfsbackendgphoto2.c:2589 ../daemon/gvfsbackendgphoto2.c:3211
+msgid "Error renaming dir"
+msgstr "Грешка во преименувањето на директориумот"
+
+#: ../daemon/gvfsbackendgphoto2.c:2601 ../daemon/gvfsbackendgphoto2.c:3223
+msgid "Error renaming file"
+msgstr "Грешка во преименувањето на датотеката"
+
+#: ../daemon/gvfsbackendgphoto2.c:2664
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Directory „%s“ не е празен"
+
+#: ../daemon/gvfsbackendgphoto2.c:2675
+msgid "Error deleting directory"
+msgstr "Грешка во бришењето на директориумот"
+
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "Error deleting file"
+msgstr "Грешка во бришењето на датотеката"
+
+#: ../daemon/gvfsbackendgphoto2.c:2752
+msgid "Can't write to directory"
+msgstr "Не можам да запишам во директориумот"
+
+#: ../daemon/gvfsbackendgphoto2.c:2799
+msgid "Cannot allocate new file to append to"
+msgstr "Не можам да алоцирам нова датотека на која што ќе додадам"
+
+#: ../daemon/gvfsbackendgphoto2.c:2813
+msgid "Cannot read file to append to"
+msgstr "Не можам да ја прочитам датотеката на која што треба да додадам"
+
+#: ../daemon/gvfsbackendgphoto2.c:2823
+msgid "Cannot get data of file to append to"
+msgstr "Не можам да ги добијам податоците од датотеката на која што треба да додадам"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Error writing file"
+msgstr "Грешка во запишувањето на датотеката"
+
+#: ../daemon/gvfsbackendgphoto2.c:3156
+msgid "Not supported (not same directory)"
+msgstr "Не е поддржано (не е истиот директориум)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3168
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Не е поддржано (src е директориум, dst е директориум)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3176
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Не е поддржано (src е датотека, dst е постоечка датотека)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Не е поддржано (src е датотека, dst е директориум)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Грешка на HTTP клиентот: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (невалидно енкодирање)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Известувањето за директориуми не е поддржано"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windows мрежа"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Локална мрежа"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Надгледувач на локации на мрежите"
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "%s на %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "Врската со уредот е изгубена"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "Уредот бара ажурирање на софтверот"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "ssh програмата неочекувано излезе"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Името на хостот не е познато"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Нема рута до хостот"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "Врската е одбиена од серверот"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Проверката на клучот на хостот не успеа"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "Не успеав да ја подигнам програмата ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Не успеав да ја подигнам програмата ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Времето за најава истече"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Внесете тајна фраза за клучот"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Внесете лозинка"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "Не можам да ја испратам лозинката"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Најави се секако"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Откажи најава"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Идентитетот на далечниот компјутер (%s) е непознат.\n"
+"Ова се случува кога се најавувате на некој компјутер з апрв пат.\n"
+"\n"
+"Идентитетот испратен на далечниот компјутер %s. Ако сакате да бидете "
+"апсолутно сигурни дека е сигурно да продолжите, контактирајте го Вашиот "
+"систем администратор."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Дијалогот за најава е откажан"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "Не можам да испратам потврда за идентитет"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Грешка во протоколот"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp на %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "Не успеав да најдам поддржана ssh команда"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Неуспех"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "Добиен е невалиден одговор"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Грешка при креирањето на бекап датотека: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "Не успеав да ја создадам привремената датотека"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr "Не можам да го преместам директориумот над друг директориум"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Потребна е лозинка за споделувањето %s на %s"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Внатрешна грешка (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr "Не успеав да го монтирам споделувањето од Windows"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr "Неподдржан тип на хостирање"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Не успеа креирањето на бекап датотека: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Грешка во бришењето на датотеката: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Грешка во преместувањето на датотеката: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Грешка во отстранувањето на целната датотека: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr "Не можам да го преместам директориумот рекурзивно"
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr "Сервис за датотечен систем на Windows споделувања"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows споделувања на %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "Оваа датотека не може да се монтира"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Не е обична датотека"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Сервис за датотечен систем за Windows мрежа"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Ѓубре"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (во ѓубрето)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "Не можам да ја избришам корпата за ѓубре"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Не е поддржано известувањето за директориумот за ѓубре"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Невалиден тип на бекенд"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Грешка при испраќањето на fd: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Операцијата не е поддржана од бекендот"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Симболичките врски не се креирани од бекендот"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "Невалидна порака од dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Замени стар демон."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Не го стартувај fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS демон"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Главен даемон за GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Пробајте „%s --help“ за повеќе информации."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "Невалидни аргументи од креираното дете"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Автоматското монтирање не успеа: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "Одредената локација не е монтирана"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "Одредената локација не е поддржана"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "Локацијата е веќе монтирана"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "Локацијата не може да се монтира"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Флопи уред"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Софтверски RAID уред"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB уред"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA уред"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI уред"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire уред"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Уред со ленти"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash уред"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick уред"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia уред"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC уред"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip уред"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz уред"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Преносен уред"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Уред за mass storage"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Не успеав да ги извадам медиумите; еден или повеќе простори на медиумите се "
+"зафатени."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+msgid "Mixed Audio/Data Disc"
+msgstr "Мешан диск со аудио/податоци"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, c-format
+msgid "%s Media"
+msgstr "%s медиум"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s енкриптирани податоци"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM диск"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Празен CD-ROM диск"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R диск"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Празен CD-R диск"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Празен CD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM диск"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Празен DVD-ROM диск"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM диск"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Празен DVD-RAM диск"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Празен DVD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R диск"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Празен DVD+R диск"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW диск"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Празен DVD+RW диск"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL диск"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Празен DVD+R DL диск"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray диск"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Празен Blu-Ray диск"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R диск"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Празен Blu-Ray R диск"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW диск"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Празен Blu-Ray RW диск"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD диск"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Празен HD DVD диск"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R диск"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Празен HD DVD-R диск"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Празен HD DVD-RW диск"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO диск"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Празен MO диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Празен диск"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: грешка во отворањето на датотеката: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, грешка, ја запишувам во stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: грешка во читањето: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: грешка во затворањето: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - наведете LOCATIONS на стандардниот влез."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Наведете датотеки од локации и испечати ги на стандардниот излез. Работи "
+"самосо алатката cat, но со користење на gvfs локација наместообични "
+"датотеки: на пример, можете да користите smb://server/resource/file.txt како "
+"локација."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Забелешка: Само насочете го стрипот со цевка преку cat ако ви требаат опции "
+"за форматирање како -n, -T или други."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: недостасуваат локации"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: грешка во отворањето на локацијата: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: грешка при лансирање на апликацијата: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - отвори FILES со регистрираната апликација."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Отвора датотека(и) со стандардната апликација регистрирана за справување со "
+"овој тип на датотеки."
+
+#~ msgid "File unavailable"
+#~ msgstr "Датотеката е недостапна"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Медиум од %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Медиум од %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Медиум од %.1f GB"
+
diff --git a/trunk/po/ml.po b/trunk/po/ml.po
new file mode 100644
index 00000000..35fdc99c
--- /dev/null
+++ b/trunk/po/ml.po
@@ -0,0 +1,1564 @@
+# translation of gvfs.ml.po to Malayalam
+# translation of gvfs.ml.po to
+# Copyright (C) 2008 gvfs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Ani Peter <apeter@redhat.com>, 2008.
+# Hari Vishnu <harivishnu@gmail.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.ml\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-08-15 07:26+0000\n"
+"PO-Revision-Date: 2008-08-15 13:20+0530\n"
+"Last-Translator: Hari Vishnu <harivishnu@gmail.com>\n"
+"Language-Team: SMC - Malayalam <smc-discuss@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr "പ്രവര്‍ത്തനം പിന്തുണയ്ക്കുന്നില്ല, ഫയലുകള്‍ പല മൌണ്ടുകളിലാണു്"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "സ്ട്രീം ഫയല്‍ ഡിസ്ക്രിപ്റ്റര്‍ ലഭ്യമായില്ല"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr "open-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr "സ്ട്രീം ഫയല്‍ ഡിസ്ക്രിപ്റ്റര്‍ ലഭ്യമായില്ല"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "കോളില്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "ഉള്‍പ്പെടുത്തിയിരിക്കുന്ന മൌണ്ട് ലഭ്യമാകുന്നില്ല"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "%s എന്ന സാധുവല്ലാത്ത ഫയല്‍നാമം"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file-ല്‍ നിന്നും സാധുവല്ലാത്ത മറുപടി"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "സ്ട്രീം സമ്പ്രദായത്തില്‍ പിഴവ്: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "സ്ട്രീമിന്റെ അവസാനം"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "പ്രവര്‍ത്തനം റദ്ദാക്കിയിരിക്കുന്നു"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "സ്ട്രീമില്‍ സീക്ക് പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "ക്വറി ഇന്‍ഫോ പ്രവര്‍ത്തനം പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "സ്ട്രീമില്‍ ക്വറിന്‍ഫോ പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "മൌണ്ട് വിവരങ്ങള്‍ ലഭ്യമാക്കുന്നതിനിടയില്‍ പിശക്: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "നിരന്തരപ്രവൃത്തിയുമായി ബന്ധപ്പെടുന്നതില്‍ പിശക്: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "സോക്കറ്റ് ഉണ്ടാക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "സോക്കറ്റുമായി ബന്ധപ്പെടുന്നതില്‍ പിശക്: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "സാധുവല്ലാത്ത ഫയല്‍ വിവര ശൈലി"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "സാധുവല്ലാത്ത ആട്രിബ്യൂട്ട് ഇന്‍ഫോ ലിസ്റ്റ് ഉള്ളടക്കം"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "ഡി-ബസുമായി ബന്ധപ്പെടുന്നതില്‍ പിശക്: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ഫയല്‍ സിസ്റ്റം സേവനം"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "പിശക്: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ഉപയോഗിക്കേണ്ട വിധം: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ഉപയോഗിക്കേണ്ട വിധം: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ഏത് തരം മൌണ്ട് എന്ന് വ്യക്തമാക്കിയിട്ടില്ല"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s-നുള്ള മൌണ്ട് പോയിന്റ് നിലവില്‍ പ്രവര്‍ത്തിക്കുന്നു"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "മൌണ്ട് ഡെമണ്‍ ആരംഭിക്കുന്നതില്‍ പിശക്"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "%s-ല്‍ /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "ഹോസ്റ്റിന്റെ നാമം വ്യക്തമാക്കിയിട്ടില്ല"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1448 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+msgid "Invalid mount spec"
+msgstr "സാധുവല്ലാത്ത മൌണ്ട്"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "ഫയല്‍ നിലവിലില്ല"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "ഫയല്‍ ഒരു തട്ടു് അല്ല"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "ബേണ്‍"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "താല്‍ക്കാലിക തട്ടു് ഉണ്ടാക്കുവാന്‍ സാധ്യമായില്ല"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1978 ../daemon/gvfsbackendgphoto2.c:2687
+#, c-format
+msgid "No such file or directory"
+msgstr "ഈ പേരില്‍ ഒരു ഫയലോ തട്ടോ ഇല്ല"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2035
+msgid "Directory not empty"
+msgstr "തട്ടു് ശൂന്യമല്ല"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr "നിലവിലുള്ള തട്ടായി ഫയല്‍ പകര്‍ത്തുവാന്‍ സാധ്യമല്ല"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "സിഡി/ഡിവിഡി സൃഷ്ടാവ്"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2760
+msgid "File exists"
+msgstr "ഫയല്‍ നിലവിലുണ്ട്"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr "പറഞ്ഞിരിക്കുന്ന വഴിയില്‍ ഇങ്ങനെ ഒരു ഫയല്‍ അല്ലെങ്കില്‍ തട്ടു് ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr "നിലവിലുള്ള തട്ടായി മറ്റൊരു തട്ടു് പകര്‍ത്തുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Target file exists"
+msgstr "ലക്ഷ്യസ്ഥാനത്തു് ഫയലുണ്ടു്"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr "ആവര്‍ത്തിച്ച് തട്ടു് പകര്‍ത്തുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2345
+#: ../daemon/gvfsbackendgphoto2.c:2553 ../daemon/gvfsbackendgphoto2.c:2648
+#: ../daemon/gvfsbackendgphoto2.c:2739
+msgid "Not supported"
+msgstr "പിന്തുണ ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot connect to the system bus"
+msgstr "സിസ്റ്റം ബസ്സുമായി ബന്ധപ്പെടാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot create libhal context"
+msgstr "ലിബ്-ഹാല്‍ കോണ്ടെക്സ്റ്റ് ഉണ്ടാക്കാന്‍ കഴിഞ്ഞില്ല"
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1427
+msgid "Cannot initialize libhal"
+msgstr "ലിബ്-ഹാല്‍ തുടങ്ങാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr "ഡ്രൈവ് വ്യക്തമാക്കിയിട്ടില്ല"
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ഡ്രൈവ് %s ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ഡ്രൈവ് %s-ല്‍ ഓഡിയോ ഫയലുകള്‍ ലഭ്യമല്ല"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr "സി.ഡി.ഡി.എ മൗണ്ട് %s-ഏല്‍"
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "ഓഡിയോ ഡിസ്ക്"
+
+#: ../daemon/gvfsbackendcdda.c:356
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ഫയല്‍ സിസ്റ്റം തിരക്കിലാണ്: %d ഫയല്‍ തുറക്കുന്നിരിയ്ക്കുന്നു"
+msgstr[1] "ഫയല്‍ സിസ്റ്റം തിരക്കിലാണ്: %d ഫയലുകള്‍ തുറക്കുന്നിരിയ്ക്കുന്നു"
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ഡ്രൈവ് %s-ല്‍ %s എന്നൊരു ഫയല്‍ ലഭ്യമല്ല"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ഡ്രൈവ് %s-ല്‍ പാരനോയിയയില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ഡ്രൈവ് %s-ല്‍ സ്ട്രീമില്‍ തിരയുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1708
+#, c-format
+msgid "No such file"
+msgstr "അങ്ങനെ ഒരു ഫയല്‍ ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ഫയല്‍ നിലവിലില്ല, അല്ലെങ്കില്‍ ഇത് ഒരു ഓഡിയോ ട്രാക്കല്ല"
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr "ശബ്ദ സി.ഡി ഫയല്‍ സിസ്റ്റം സേവനം"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "കമ്പ്യൂട്ടര്‍"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ഫയല്‍ സിസ്റ്റം"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1700
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+msgid "Can't open directory"
+msgstr "തട്ടു് തുറക്കുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "മൌണ്ട് ചെയ്യുവാന്‍ കഴിയുന്ന ഫയല്‍ തുറക്കുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "ആന്തരിക പിഴവ്: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "ഫയല്‍ മൌണ്ട് ചെയ്യുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "ഡ്രൈവില്‍ മാധ്യമം ഇല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "ഒരു മൌണ്ടു് ചെയ്യാവുന്ന ഫയല്‍ അല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "ഫയല്‍ അണ്‍മൌണ്ട് ചെയ്യുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "ഫയല്‍ ലഭ്യമാക്കുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1515
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP പിഴവ്: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "മറുപടി പാഴ്സ് ചെയ്യുവാന്‍ സാധ്യമായില്ല"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "മറുപടി ശൂന്യം"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "സെര്‍വറില്‍ നിന്നും അപ്രതീക്ഷിതമായ മറുപടി"
+
+#: ../daemon/gvfsbackenddav.c:1148 ../daemon/gvfsbackenddav.c:1650
+msgid "Response invalid"
+msgstr "സാധുവല്ലാത്ത മറുപടി"
+
+#: ../daemon/gvfsbackenddav.c:1291
+msgid "WebDAV share"
+msgstr "WebDAV ഷെയര്‍"
+
+#: ../daemon/gvfsbackenddav.c:1293
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s-നുള്ള അടയാളവാക്കു് നല്‍കുക"
+
+#: ../daemon/gvfsbackenddav.c:1296
+msgid "Please enter proxy password"
+msgstr "ദയവായി പ്രോക്സി അടയാളവാക്കു് നല്‍കുക"
+
+#: ../daemon/gvfsbackenddav.c:1519 ../daemon/gvfsbackenddav.c:1523
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV സജ്ജമായ ഷെയര്‍ അല്ല"
+
+#: ../daemon/gvfsbackenddav.c:1546
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV %s-ഏല്‍"
+
+#: ../daemon/gvfsbackenddav.c:1606 ../daemon/gvfsbackenddav.c:1679
+msgid "Could not create request"
+msgstr "ആവശ്യം അറിയിക്കുവാന്‍ സാധിച്ചില്ല"
+
+#: ../daemon/gvfsbackenddav.c:1742 ../daemon/gvfsbackenddav.c:1995
+#: ../daemon/gvfsbackenddav.c:2106 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr "ലക്ഷ്യസ്ഥാനത്തുള്ള ഫയല്‍ നിലവിലുണ്ട്"
+
+#: ../daemon/gvfsbackenddav.c:1815 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr "ഫയല്‍ പുറത്ത് നിന്നും മാറ്റിയിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackenddav.c:1846 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr "കരുതല്‍ പകര്‍പ്പു് ഫയല്‍ ഉണ്ടാക്കുന്നത് പരാജയപ്പെട്ടു"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "ഡി.എന്‍.എസ്-എസ്.ഡി(dns-sd)"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "ഫയല്‍ അല്ലെങ്കില്‍ തട്ടു് മോണിറ്റര്‍ ചെയ്യാന്‍ കഴിയുന്നില്ല"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "ഡി.എന്‍.എസ്-എസ്.ഡി(Dns-SD)"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "ശ്രൃംഖല"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "അക്കൗണ്ടുകള്‍ക്ക് പിന്തുണ ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "ഹോസ്റ്റ് ബന്ധം അടച്ചു"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "വിവര ബന്ധം തുടങ്ങാന്‍ കഴിയുന്നില്ല. നിങ്ങളുടെ തീ-ഭിത്തി ഇത് തടയുന്നുണ്ടാവാം."
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "വിവര ബന്ധം അടച്ചു"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "പ്രവര്‍ത്തനം റദ്ദാക്കിയിരിക്കുന്നു "
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "സെര്‍വറില്‍ സ്ഥലം ബാക്കിയില്ല"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "പ്രവര്‍ത്തനം പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "അനുവാദമില്ല"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "പേജ് തരം അറിയുന്നതല്ല"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "സാധുവല്ലാത്ത ഫയല്‍നാമം"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "സാധുവല്ലാത്ത മറുപടി"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "പൊട്ടിയ പ്രക്ഷേപണം"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "ഹോസ്റ്റുമായി ബന്ധപ്പെടാന്‍ കഴിഞ്ഞില്ല"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s-നുള്ള എഫ്.ടി.പി-ക്കുള്ള അടയാളവാക്കു് നല്‍കുക"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "അടയാളവാക്കിനുള്ള സംഭാഷണം റദ്ദാക്കിയിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "%s-ല്‍ ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%2$s-ല്‍ %1$s-ആയി ftp"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "ഫയലൊരു തട്ടാണു്"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "കരുതല്‍ പകര്‍പ്പുകള്‍ പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "ഫയലിന്റെ പേരു് വളരെ വലുതാണു്"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "സാധുവല്ലാത്ത ഉദ്ദേശ ഫയല്‍നാമം"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ഫയല്‍ അല്ലെങ്കില്‍ തട്ടു് നേരത്തെ തന്നെയുണ്ട്"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: ഈ പേരില്‍ ഒരു ഫയലോ തട്ടോ ഇല്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: എന്ന സാധുവല്ലാത്ത ഫയല്‍നാമം"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: പിന്തുണ ലഭ്യമല്ല"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ഡിജിറ്റല്‍ ക്യാമറ (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s ക്യാമറ"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ശബ്ദ പ്ലേയര്‍"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "ക്യാമറ"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "ശബ്ദ പ്ലേയര്‍"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325
+msgid "Error listing folders to figure out ignore prefix"
+msgstr "അവഗണന മുന്‍-വാചകം കണ്ടു പിടിക്കാന്‍ അറകളുടെ പട്ടിക ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1442
+msgid "No device specified"
+msgstr "ഉപകരണം വ്യക്തമാക്കിയിട്ടില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:1459
+msgid "Cannot create gphoto2 context"
+msgstr "ജി.പി.ഫോടോ2 കോണ്ടെക്സ്റ്റ് ഉണ്ടാക്കാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469
+msgid "Error creating camera"
+msgstr "ക്യാമറ ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1482
+msgid "Error creating port info list"
+msgstr "പോര്‍ട് വിവര പട്ടിക ഉണ്ടാക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1492
+msgid "Error loading info list"
+msgstr "വിവര പട്ടിക തുറക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1504
+msgid "Error looking up port info from port info list"
+msgstr "പോര്‍ട് വിവര പട്ടികയില്‍ നിന്നും പോര്‍ട് വിവരങ്ങള്‍ കണ്ടുപിടിക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error getting port info from port info list"
+msgstr "പോര്‍ട് വിവര പട്ടികയില്‍ നിന്നും പോര്‍ട് വിവരങ്ങള്‍ കിട്ടുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1527
+msgid "Error setting port info"
+msgstr "പോര്‍ട് വിവരം സെറ്റപ്പ് ചെയ്യുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1538
+msgid "Error initializing camera"
+msgstr "ക്യാമറ ആരംഭിക്കാന്‍ കഴിയുന്നില്ല"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1552
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "ജി.പി.ഫോടോ2 മൗണ്ട് %s-ഏല്‍"
+
+#: ../daemon/gvfsbackendgphoto2.c:1627
+msgid "No camera specified"
+msgstr "ക്യാമറ ഒന്നും വ്യക്തമാക്കിയിട്ടില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:1655
+#, c-format
+msgid "File system is busy: %d open files"
+msgstr "ഫയല്‍ സിസ്റ്റം തിരക്കിലാണ്: %d ഫയല്‍ തുറന്നിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendgphoto2.c:1716
+msgid "Error creating file object"
+msgstr "ഫയല്‍ വസ്തു ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1730
+msgid "Error getting file"
+msgstr "ഫയല്‍ കിട്ടുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1739
+msgid "Error getting data from file"
+msgstr "ഫയലില്‍ നിന്നും വിവരങ്ങള്‍ കിട്ടുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1833 ../daemon/gvfsbackendgphoto2.c:3007
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "%s ക്യാമറയില്‍ അകത്തേക്കുള്ള സ്റ്റ്രീം കണ്ടെത്തുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:1972 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "ഒരു തട്ടു് അല്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:2005
+msgid "Error listing folders"
+msgstr "അറ പട്ടികകള്‍ ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2068
+msgid "Error listing files in folder"
+msgstr "അറയില്‍ ഫയല്‍ പട്ടികകള്‍ ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2357
+msgid "Error creating directory"
+msgstr "അറ ഉണ്ടാക്കുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2565
+msgid "Name already exists"
+msgstr "പേര് നേരത്തേ തന്നെ ഉണ്ട്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2576 ../daemon/gvfsbackendgphoto2.c:3197
+msgid "New name too long"
+msgstr "പുതിയ പേര് വളരെ വലുതാണ്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2586 ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Error renaming dir"
+msgstr "അറ പേര് മാറ്റുനത്തില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2598 ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Error renaming file"
+msgstr "ഫയല്‍ പേര് മാറ്റുനത്തില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2661
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "തട്ടു് '%s' ശൂന്യമല്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:2672
+msgid "Error deleting directory"
+msgstr "അറ കളയുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2697
+msgid "Error deleting file"
+msgstr "ഫയല്‍ കളയുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:2749
+msgid "Can't write to directory"
+msgstr "അറയിലേക്ക് എഴുതാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:2796
+msgid "Cannot allocate new file to append to"
+msgstr "ഇത് ചേര്‍ക്കണ്ട ഫയല്‍ അലോക്കേറ്റ് ചെയ്യാന്‍ കഴിഞ്ഞില്ല (സ്ഥലം കണ്ടു പിടിക്കാന്‍ കഴിഞ്ഞില്ല)"
+
+#: ../daemon/gvfsbackendgphoto2.c:2810
+msgid "Cannot read file to append to"
+msgstr "ഇത് ചേര്‍ക്കണ്ട ഫയല്‍ വായിക്കാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:2820
+msgid "Cannot get data of file to append to"
+msgstr "ഇത് ചേര്‍ക്കണ്ട ഫയലിന്റെ വിവരങ്ങള്‍ ലഭിക്കുന്നില്ല"
+
+#: ../daemon/gvfsbackendgphoto2.c:3106
+msgid "Error writing file"
+msgstr "ഫയല്‍ എഴുതുന്നതില്‍ പിശക്"
+
+#: ../daemon/gvfsbackendgphoto2.c:3153
+msgid "Not supported (not same directory)"
+msgstr "പിന്തുണയ്ക്കുന്നില്ല (അതേ അറയല്ല)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "പിന്തുണയ്ക്കുന്നില്ല (സ്രോതസ്സ് അറയാണ്, ലക്ഷ്യം അറയാണ്)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3173
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "പിന്തുണയ്ക്കുന്നില്ല (സ്രോതസ്സ് അറയാണ്, ലക്ഷ്യം നിലവിലുള്ള ഫയലാണ്)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3185
+msgid "Not supported (src is file, dst is dir)"
+msgstr "പിന്തുണയ്ക്കുന്നില്ല (സ്രോതസ്സ് ഫയലാണ് , ലക്ഷ്യം അറയാണ്)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP ക്ലയന്റില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (സാധുവല്ലാത്ത എന്‍കോഡിങ്)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "തട്ടിനുള്ള അറിയിപ്പ് പിന്തുണയ്ക്കുന്നില്ല"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "വിന്‍ഡോസ് ശൃംഖല"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "പ്രാദേശിക ശ്രംഖല (നെറ്റ്വര്‍ക്ക്)"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "ശ്രംഖല സ്ഥാനം നിരീക്ഷിയ്ക്കുക"
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr "%s-ല്‍ %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "ഉപകരണവുമായുള്ള ബന്ധം നഷ്ടപ്പെട്ടു"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "ഉപകരണം ഒരു സോഫ്റ്റ്‌വെയര്‍ പുതുക്കല്‍ ആവശ്യപ്പെടുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "ssh പ്രോഗ്രാമില്‍ നിന്നും അപ്രതീക്ഷിതമായി പുറത്തു് കടന്നിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "ഹോസ്റ്റിന്റെ പേരു് ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "ഹോസ്റ്റിലേക്കുള്ള വഴി ലഭ്യമല്ല"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "സെര്‍വര്‍ ബന്ധം നിഷേധിച്ചിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "ഹോസ്റ്റ് കീയുടെ തിരിച്ചറിയല്‍ പരാജയപ്പെട്ടിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "ssh പ്രോഗ്രാം സ്പോണ്‍ ചെയ്യുവാന്‍ സാധ്യമായില്ല"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh പ്രോഗ്രാം സ്പോണ്‍ ചെയ്യുവാന്‍ സാധ്യമായില്ല: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "ലോഗിന്‍ ചെയ്യുന്നതിനുള്ള സമയം കഴിഞ്ഞിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "കീയ്ക്കുള്ള അടയാളവാചകം നല്‍കുക"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "അടയാളവാക്കു് നല്‍കുക"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "അടയാളവാക്കു് അയയ്ക്കുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "ഏതായാലും അകത്തുകയറുക"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "അകത്തുകയറല്‍ റദ്ദാക്കുക"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"ദൂര കമ്പ്യൂടറുടെ (%s) തിരിച്ചറിയല്‍ അറിയുന്നതല്ല.\n"
+"ഇത് നിങ്ങള്‍ ഒരു കമ്പ്യൂടറില്‍ ആദ്യത്തെ തവണ അകത്തുകയറുമ്പോള്‍ സംഭവിയ്ക്കുന്നു.\n"
+"\n"
+"ദൂര കമ്പ്യൂടര്‍ അയച്ച ഹിരിച്ചറിയല്‍ %s ആണ്. നിങ്ങള്‍ക്ക് വളരെ ഉറപ്പുണ്ടെങ്കില്‍ തുടരാം, സിസ്റ്റം "
+"പരിപാലകനുമായി ബന്ധപ്പെടുക."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "അകത്തകയറുന്നതിനുള്ള സംഭാഷണം റദ്ദാക്കിയിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "ഹോസ്റ്റ് തിരിച്ചറിയല്‍ വിവരം അയയ്ക്കാന്‍ കഴിയുന്നില്ല"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "സമ്പ്രദായത്തില്‍ പിഴവ്"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "%s-ല്‍ sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "പിന്തുണയ്ക്കുന്ന ssh കമാന്‍ഡ് ലഭ്യമായില്ല"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "പരാജയം"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "സാധുവല്ലാത്ത മറുപടി ലഭിച്ചിരിക്കുന്നു"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "കരുതല്‍ പകര്‍പ്പു് ഫയല്‍ ഉണ്ടാക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "താല്‍ക്കാലിക ഫയല്‍ ഉണ്ടാകുവാന്‍ സാധ്യമായില്ല"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr "ഒരു തട്ടിന്റെ പുറത്ത് മറ്റൊരെണ്ണം നീക്കുവാന്‍ സാധ്യമല്ല"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s-ല്‍ %s പങ്കിടുന്നതിനായി അടയാളവാക്കു് ആവശ്യമുണ്ട്"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "ആന്തരിക പിശക് (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+msgid "Failed to mount Windows share"
+msgstr "വിന്‍ഡോസ് ഷെയര്‍ മൌണ്ട് ചെയ്യുന്നതില്‍ പരാജയം"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+msgid "Unsupported seek type"
+msgstr "പിന്തുണലഭ്യമല്ലാത്ത തരത്തിലുള്ള തിരച്ചില്‍"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "കരുതല്‍ പകര്‍പ്പിനുള്ള ഫയല്‍ ഉണ്ടാക്കുന്നത് പരാജയപ്പെട്ടു: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ഫയല്‍ നീക്കം ചെയ്യുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ഫയല്‍ നീക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "ലക്ഷ്യസ്ഥാനത്തുള്ള ഫയല്‍ നീക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr "ആവര്‍ത്തിച്ച് തട്ടു് നീക്കുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendsmb.c:1928
+msgid "Windows Shares Filesystem Service"
+msgstr "വിന്‍ഡോസ് ഷെയറുകളുടെ ഫയല്‍ സിസ്റ്റം സേവനം"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s-ല്‍ വിന്‍ഡോസ് ഷെയറുകള്‍"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "ഫയല്‍ മൌണ്ടു് ചെയ്യാവുന്ന അല്ല"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "ഒരു സാധാരണ ഫയല്‍ അല്ല"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "വിന്‍ഡോസ് ശൃംഖല ഫയല്‍സിസ്റ്റം സേവനം"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1226
+msgid "Trash"
+msgstr "ചവറ്റുകുട്ട"
+
+#: ../daemon/gvfsbackendtrash.c:1016
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (ചവറ്റുകുട്ടയില്‍)"
+
+#: ../daemon/gvfsbackendtrash.c:1327
+msgid "Can't delete trash"
+msgstr "ചവറ്റുകുട്ട നീക്കം ചെയ്യുവാന്‍ സാധ്യമല്ല"
+
+#: ../daemon/gvfsbackendtrash.c:1674 ../daemon/gvfsbackendtrash.c:1749
+msgid "Trash directory notification not supported"
+msgstr "ചവറ്റുകുട്ടയ്ക്കുള്ള അറിയിപ്പ് പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "സാധുവല്ലാത്ത ബാക്കെന്‍ഡ് രീതി"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd അയയ്ക്കുന്നതില്‍ പിശക്: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "ബാക്കെന്‍ഡ് പ്രവര്‍ത്തനം പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "ബാക്കെന്‍ഡ് സിംലിങ്കുകള്‍ പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "സാധുവല്ലാത്ത ഡിബസ് സന്ദേശം"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "പഴയ ഡെമണ്‍ മാറ്റി എഴുതുക."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "ഫ്യൂസ് തുടങ്ങുവാന്‍ പാടില്ല."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS ഡെമണ്‍"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS-നുള്ള പ്രധാന ഡെമണ്‍"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "കൂടുതല്‍ വിവരങ്ങള്‍ക്കായി \"%s --help\" ഉപയോഗിക്കുക."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "സ്പോണ്‍ഡ് ചൈള്‍ഡില്‍ നിന്നും സാധുവല്ലാത്ത ആര്‍ഗ്യുമെന്റുകള്‍"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "ഓട്ടോമൌണ്ട് പരാജയപ്പെട്ടിരിക്കുന്നു: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "പറഞ്ഞിരിക്കുന്ന സ്ഥലം മൌണ്ട് ചെയ്തിട്ടില്ല"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "പറഞ്ഞിരിക്കുന്ന സ്ഥലം പിന്തുണയ്ക്കുന്നില്ല"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "സ്ഥലം നിലവില്‍ മൌണ്ട് ചെയ്തിരിക്കുന്നു"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "സ്ഥലം മൌണ്ട് ചെയ്യുവാന്‍ സാധ്യമല്ല"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "സിഡി-റോം"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "സിഡി-ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "സിഡി-ആര്‍ഡബ്ലിയു"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "ഡിവിഡി-റോം"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "ഡിവിഡി+ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "ഡിവിഡി+ആര്‍ഡബ്ലിയു"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "ഡിവിഡി-ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "ഡിവിഡി-ആര്‍ഡബ്ലിയു"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "ഡിവിഡി-റാം"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "ഡിവിഡി±ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "ഡിവിഡി±ആര്‍ഡബ്ലിയു"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "എച്ഡിഡിവിഡി"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "എച്ഡിഡിവിഡി-ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "എച്ഡിഡിവിഡി-ആര്‍ഡബ്ലിയു"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "ബ്ലു-റേ"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "ബ്ലു-റേ-ആര്‍"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "ബ്ലു-റേ-ആര്‍ഇ"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ‍ഡ്രൈവ്"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ഫ്ലോപ്പി ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "സോഫ്റ്റ്‌വെയര്‍ റെയിഡ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "യുഎസ്ബി ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "അടാ ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "സ്കസി ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "ഫയര്‍വയര്‍ ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "ടേപ്പ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "കോംപാക്ട്ഫ്ലാഷ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "മെമ്മറിസ്റ്റിക് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "സ്മാര്‍ട്ട്മീഡിയാ ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "എസ്ഡി/എംഎംസി ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "സിപ്പ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "ജാസ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "തംബ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "മാസ് സ്റ്റോറേജ് ഡ്രൈവ്"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"സിഡി പുറത്തെടുക്കുന്നതില്‍ പരാജയപ്പെട്ടു; മീഡിയയിലുള്ള ഒന്നോ അതിലധികമോ വോള്യമുകള്‍ തിരക്കിലാണ്."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f കെബി"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f എംബി"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f ജിബി"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+msgid "Mixed Audio/Data Disc"
+msgstr "മിക്സ്ഡ് ഓഡിയോ/ഡേറ്റാ ഡിസ്ക്"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, c-format
+msgid "%s Media"
+msgstr "%s മീഡിയാ"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s എന്‍ക്രിപ്റ്റഡ് ഡേറ്റാ"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "സിഡി-റോം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ഒഴിഞ്ഞ സിഡി-റോം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "സിഡി-ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ഒഴിഞ്ഞ സിഡി-ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "സിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ഒഴിഞ്ഞ സിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "ഡിവിഡി-റോം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവിഡി-റോം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "ഡിവിഡി-റാം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവിഡി-റാം ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "ഡിവിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "ഡിവി‍ഡി+ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവി‍ഡി+ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "ഡിവി‍ഡി+ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവി‍ഡി+ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "ഡിവി‍ഡി+ആര്‍ ഡിഎല്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ഒഴിഞ്ഞ ഡിവി‍ഡി+ആര്‍ ഡിഎല്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "ബ്ലു-റേ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ഒഴിഞ്ഞ ബ്ലു-റേ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "ബ്ലു-റേ ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ഒഴിഞ്ഞ ബ്ലു-റേ ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "ബ്ലു-റേ ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ഒഴിഞ്ഞ ബ്ലു-റേ ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "എച്ഡി ഡിവിഡി ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ഒഴിഞ്ഞ എച്ഡി ഡിവിഡി ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "എച്ഡി ഡിവിഡി-ആര്‍ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ഒഴിഞ്ഞ എച്ഡി ഡിവിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "എച്ഡി ഡിവിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ഒഴിഞ്ഞ എച്ഡി ഡിവിഡി-ആര്‍ഡബ്ലിയു ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "എംഓ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ഒഴിഞ്ഞ എംഓ ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "ഡിസ്ക്"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ഒഴിഞ്ഞ ഡിസ്ക്"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ഫയല്‍ തുറക്കുന്നതില്‍ പിശക്: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout-ലേക്ക് എഴുതുന്നതില്‍ പിശക്"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: വായിക്കുന്നതില്‍ പിശക്: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:അടയ്ക്കുന്നതില്‍ പിശക്: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "സ്ഥാനം... - സാധാരണ ഔട്ട്പുട്ടിലേക്ക് സ്ഥാനങ്ങള്‍ കൂട്ടിചേര്‍ക്കുക."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"സ്ഥാനങ്ങളില്‍ ഫയലുകള്‍ കൂട്ടിചേര്‍ത്ത് സാധാരണ ഔട്ട്പുട്ടിലേക്ക് പ്രിന്റ് ചെയ്യുക. പഴയ cat പോലെ തന്നെ "
+"പ്രവര്‍ത്തിക്കുന്നു, പക്ഷേ ലോക്കല്‍ ഫയലുകള്‍ക്ക് പകരം gvfs സ്ഥാനം ഉപയോഗിക്കുന്നു: ഉദാഹരണത്തിന്, "
+"നിങ്ങള്‍ക്ക് കൂട്ടിചേര്‍ക്കുന്നതിനുള്ള സ്ഥാനമായി smb://server/resource/file.txt എന്ന് "
+"ഉപയോഗിക്കാം."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"കുറിപ്പ്: -n, -T അല്ലെങ്കില്‍ other എന്നിങ്ങനെയുള്ള ഫോര്‍മാറ്റിങ് ഉപാധികള്‍ ആവശ്യമെങ്കില്‍ cat "
+"കമാന്‍ഡില്‍ | ഉപയോഗിക്കുക"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ലഭ്യമല്ലാത്ത സ്ഥലങ്ങള്‍"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: സ്ഥലം തുറക്കുന്നതില്‍ പിശക്: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: പ്രയോഗം ലഭ്യമാക്കുന്നതില്‍ പിശക്: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ഫയലുകള്‍... - രജിസ്ടര്‍ ചെയ്തിരിക്കുന്ന പ്രയോഗങ്ങളുപയോഗിച്ച് ഫയലുകള്‍ തുറക്കുക."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "ഇത്തരത്തിലുള്ള ഫയലുകള്‍ കൈകാര്യം ചെയ്യുന്നതിന് സ്വതവേയുള്ള പ്രയോഗം ഉപയോഗിച്ച് ഫയല്‍ തുറക്കുക."
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "%s-ലുള്ള ഓഡിയോ ഡിസ്ക്"
+
+#~ msgid "The file does not exist"
+#~ msgstr "ഫയല്‍ നിലവിലില്ല"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB മീഡിയാ"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB മീഡിയാ"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB മീഡിയാ"
diff --git a/trunk/po/mr.po b/trunk/po/mr.po
new file mode 100644
index 00000000..9ad92c3c
--- /dev/null
+++ b/trunk/po/mr.po
@@ -0,0 +1,1644 @@
+# translation of gvfs.HEAD.mr.po to marathi
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Sandeep Shedmake <sandeep.shedmake@gmail.com>, 2008, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD.mr\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-27 15:51+0000\n"
+"PO-Revision-Date: 2009-03-13 18:14+0530\n"
+"Last-Translator: Sandeep Shedmake <sandeep.shedmake@gmail.com>\n"
+"Language-Team: marathi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "कार्यपध्दती समर्थीत नाही, अन्य आरोहणवरील फाइलं"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "स्ट्रीम फाइल वर्णनकर्ता प्राप्त करू शकला नाही"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "उघडा पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "स्ट्रीम फाइल वर्णनकर्ता प्राप्त करू शकले नाही"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info पासून अवैध परतीचे मूल्य"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "अंतर्भूतीत आरोहण शोधू शकले नाही"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "अवैध फाइलनाव %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file पासून अवैध परतीचे मूल्य"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:628
+#: ../client/gdaemonfileinputstream.c:781
+#: ../client/gdaemonfileinputstream.c:899
+#: ../client/gdaemonfileinputstream.c:1147
+#: ../client/gdaemonfileinputstream.c:1389
+#: ../client/gdaemonfileoutputstream.c:504
+#: ../client/gdaemonfileoutputstream.c:679
+#: ../client/gdaemonfileoutputstream.c:871
+#: ../client/gdaemonfileoutputstream.c:1050
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+msgid "Operation was cancelled"
+msgstr "कार्य रद्द करण्यात आले"
+
+#: ../client/gdaemonfileinputstream.c:525
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1680
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:448
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1232
+#: ../client/gdaemonfileoutputstream.c:1242
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "स्ट्रीम शिष्टाचारातील त्रुटी: %s"
+
+#: ../client/gdaemonfileinputstream.c:533
+#: ../client/gdaemonfileinputstream.c:1690
+#: ../client/gdaemonfileoutputstream.c:456
+#: ../client/gdaemonfileoutputstream.c:1242
+msgid "End of stream"
+msgstr "स्ट्रीमचे शेवट"
+
+#: ../client/gdaemonfileinputstream.c:1328
+#: ../client/gdaemonfileoutputstream.c:979
+msgid "Seek not supported on stream"
+msgstr "श्रृंखलेवर सीक समर्थित नाही"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "आरोहण माहिती प्राप्त करतेवेळी त्रुटी: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "डीमनशी जुळवणी करतेवेळी त्रुटी: %s"
+
+#: ../client/gvfsiconloadable.c:145
+#| msgid "Invalid return value from get_info"
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read पासून अवैध return मूल्य"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "सॉकेट बनवितेवेळी त्रुटी: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "सॉकेटशी जुळवणी करतेवेळी त्रुटी: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "अवैध फाइल माहिती स्वरूपन"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "अवैध गुणधर्म माहिती यादी अनुक्रम"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error deleting file: %s"
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi प्रारंभ करतेवेळी त्रुटी आढळली: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating socket: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi रिजॉल्वर बनवितेवेळी त्रुटी आढळली: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "क्षेत्र \"%3$s\" वरील सेवा \"%2$s\" करीता \"%1$s\" निर्धारीत करतेवेळी त्रुटी आढळली"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr "क्षेत्र \"%3$s\" वरील सेवा \"%2$s\" करीता \"%1$s\" निर्धारीत करतेवेळी त्रुटी आढळली. एक किंवा त्यापेक्षा जास्त TXT रेकॉर्ड आढळले नाही. किज् आवश्यक आहे: \"%4$s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "क्षेत्र \"%3$s\" वरील सेवा \"%2$s\" करीता \"%1$s\" निर्धारीत करतेवेळी टाइम्ड् आउट झाले"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "सदोषीत dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon एनकोडींगची आवृत्ती %d हाताळू शकत नाही"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon करीता सदोषीत इनपुट डेटा"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus शी जुळवणी करतेवेळी त्रुटी: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s फाइलप्रणाली सेवा"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "चूक: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "वापरणी: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "वापरणी: %s गुणविशेष=मूल्य गुणविशेष=मूल्य ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "आरोहण प्रकार निर्धारीत नाही"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s करीता आरोहणकेंद्र आधिपासूनच कार्यरत आहे"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "आरोहण डीमन सुरू करण्यास त्रुटी"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1893
+#, c-format
+msgid "/ on %s"
+msgstr "/ आढळल्यास %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "No hostname specified"
+msgstr "यजमाननाव निश्चित केले नाही"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "अवैध अनारोहण स्पेक"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "फाइल अस्तित्वात नाही"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "फाइल संचयीका नाही"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "बनवा"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "तात्पुरती संचयीका बनविण्यास अपयशी"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "या प्रकारची फाइल किंवा संचयीका नाही"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "संचयीका रिकामी नाही"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "संचयीकावर फाइलची प्रत बनवू शकला नाही"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD निर्माता"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "फाइल उपलब्ध आहे"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "बॅकऐंड द्वारे कार्यपध्दती समर्थीत नाही"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "लक्ष मार्गात फाइल किंवा संचयीका नाही"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "संचयीकेवर संचयीकेची प्रत बनवू शकत नाही"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "लक्ष्य फाइल अस्तित्वात आहे"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "संचयीकेची पुनः प्रत बनवू शकत नाही"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "समर्थीत नाही"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+#| msgid "Could not connect to host"
+msgid "Cannot connect to the system bus"
+msgstr "प्रणाली बसशी जुळवणी प्राप्त करणे शक्य नाही"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "libhal संदर्भ बनविणे शक्य नाही"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "libhal प्रारंभ करणे अशक्य"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "ड्राइव्ह निर्धारीत नाही"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ड्राइव्ह %s शोधू शकले नाही"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ड्राइव्ह %s मध्ये आवाज फाइल समाविष्ट नाही"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s वर cdda आरोहण"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "श्राव्य डिस्क"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "फाइल प्रणाली व्यस्थ आहे: %d उघडे फाइल"
+msgstr[1] "फाइल प्रणाली व्यस्थ आहे: %d उघडे फाइलं"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ड्राइव्ह %s वरील फाइल %s नाही"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ड्राइव्ह %s वरील 'paranoia' मध्ये त्रुटी"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ड्राइव्ह %s वरील स्ट्रीम संचयनवेळी त्रुटी"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "या प्रकारची फाइल नाही"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "फाइल जी अस्तित्वात नाही किंवा ती संगीत फाइल नाही"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "ऑडीओ CD फाइलप्रणाली सेवा"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "संगणक"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "फाइलप्रणाली"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "संचयीका उघडू शकत नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "आरोहण फाइल उघडू शकले नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1034
+#, c-format
+msgid "Internal error: %s"
+msgstr "आंतरीक त्रुटी: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "फाइल आरोहण जोगी नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ड्राइव्ह मध्ये मिडीया नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "आरोहणजोगी फाइल नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "फाइल अनारोहीत करू शकत नाही"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "फाइल बाहेर काढू शकत नाही"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP त्रुटी: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "प्रतिसाद वाचू शकले नाही"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "प्रतिसाद रिकामे करा"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "सर्वर पासून अनपेक्षीत प्रतिसाद"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "अवैध प्रतिसाद"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV साठा"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s करीता परवलीचा शब्द प्रविष्ट करा"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "कृपया प्रॉक्सी परवलीचा शब्द प्रविष्ट करा"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV कार्यान्वीत साठा नाही"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+#| msgid "WebDAV share"
+msgid "WebDAV on %s"
+msgstr "%s वरील WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "विनंती बनवू शकला नाही"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3698
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "लक्ष्य फाइल आधिपासूनच अस्तित्वात आहे"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2931
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "फाइल बाह्य नुरूप संपादीत केले"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "प्रतिकृत फाइल निर्माण अपयशी"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "स्थानीक संजाळ"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "फाइल किंवा संचयीकेवर नियंत्रण नाही."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "संजाळ"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "खाते समर्थीत नाही"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "यजमानने जुळवणी बंद केली"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "माहिती जुळवणी उघडू शकत नाही. कदाचीत तुमचे फायरवॉल हे करण्यास नकारते?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "माहिती जुळवणी बंद झाली"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "कार्यपध्दती अपयशी"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "सर्वरवर रिकामी जागा नाही"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4009
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "कार्यपध्दती समर्थीत नाही"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "परवानगी नाकारली"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "पान प्रकार अपरिचीत"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "अवैध फाइलनाव"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "अवैध प्रतिसाद"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "खंडीत स्थानांतरन"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "यजमानशी जुळवणी प्राप्त करू शकला नाही"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+#| msgid "Enter password for ftp on %s"
+msgid "Enter password for ftp as %s on %s"
+msgstr "%2$s वरील %1$s ftp करीता परवलीचा शब्द प्रविष्ट करा"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s वर ftp करीता परवलीचा शब्द प्रविष्ट करा"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:871
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "परवलीचा शब्द संवाद रद्द केले"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s वरील ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s वर %s ftp म्हणून"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1957
+#: ../daemon/gvfsbackendsftp.c:3689
+msgid "File is directory"
+msgstr "फाइल संयीका आहे"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2792
+msgid "backups not supported yet"
+msgstr "बॅकऐंड अजूनही समर्थीत नाही"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "फाइलनाव खूप लांब आहे"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "अवैध लक्ष्यनीय फाइलनाव"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+#| msgid "%s: %s: error opening file: %s\n"
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: डिरेक्ट्री किंवा फाइल अस्तित्वात आहे"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+#| msgid "No such file or directory"
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: यानुरूप फाइल किंवा डिरेक्ट्री आढळली नाही"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+#| msgid "Invalid filename"
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: अवैध फाइलनाव"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+#| msgid "Not supported"
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: समर्थीत नाही"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "डीजीटल कॅमेरा (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s कॅमेरा"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ऑडिओ वादक"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "कैमेरा"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "ऑडिओ वादक"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+#| msgid "No drive specified"
+msgid "No device specified"
+msgstr "साधन निश्चित केले नाही"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 संदर्भ बनविणे अशक्य"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+#| msgid "Error creating socket: %s"
+msgid "Error creating camera"
+msgstr "कॅमेरा बनवितेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "शाधन विषयी माहिती दाखल करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "शाधन विषयी माहिती करीता शोध करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "शाधन विषयी माहिती प्राप्त करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "कॅमेरा संचारन पोर्टची मांडणी निश्चित करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "कॅमेरा प्रारंभ करतेवेळी त्रुटी आढळली"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s वर gphoto2 आरोहीत"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+#| msgid "No hostname specified"
+msgid "No camera specified"
+msgstr "कॅमेरा निश्चित केले नाही"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+#| msgid "Error creating backup file: %s"
+msgid "Error creating file object"
+msgstr "फाइल ऑबजेक्ट बनवतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+#| msgid "Error deleting file: %s"
+msgid "Error getting file"
+msgstr "फाइल प्राप्त करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+#| msgid "Error removing target file: %s"
+msgid "Error getting data from file"
+msgstr "फाइल पासून डेटा प्राप्त करतेवेळी त्रूटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "सदोषीत चिन्ह ओळखकर्ता '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+#| msgid "Error seeking in stream on drive %s"
+msgid "Error seeking in stream on camera %s"
+msgstr "कॅमेरा %s वरील स्ट्रीम सीक करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "संचयीका नाही"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+#| msgid "File doesn't exist"
+msgid "Failed to get folder list"
+msgstr "फोल्डर यादी प्राप्त करण्यास अपयशी"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+#| msgid "Target file exists"
+msgid "Failed to get file list"
+msgstr "फाइल यादी प्राप्त करण्यास अपयशी"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+#| msgid "Error creating socket: %s"
+msgid "Error creating directory"
+msgstr "डिरेक्ट्री बनवितेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+#| msgid "Target file already exists"
+msgid "Name already exists"
+msgstr "नाव आधिपासूनच अस्तित्वात आहे"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+#| msgid "filename too long"
+msgid "New name too long"
+msgstr "नवीन फाइलनाव खूप लांब आहे"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+#| msgid "Error sending fd: %s"
+msgid "Error renaming dir"
+msgstr "dir पुन्हनामांकनवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+#| msgid "Error moving file: %s"
+msgid "Error renaming file"
+msgstr "फाइल पुन्हनामांकनवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+#| msgid "Directory not empty"
+msgid "Directory '%s' is not empty"
+msgstr "डिरेक्ट्री '%s' रिकामी नाही"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+#| msgid "Error deleting file: %s"
+msgid "Error deleting directory"
+msgstr "डिरेक्ट्री नष्ट करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+#| msgid "Error deleting file: %s"
+msgid "Error deleting file"
+msgstr "फाइल नष्ट करतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+#| msgid "Can't open directory"
+msgid "Can't write to directory"
+msgstr "डिरेक्ट्री करीता लिहीणे अशक्य"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "समावेष करण्याजोगी नवीन फाइलचे वाटप करणे अशक्य"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "समावेष करण्याजोगी फाइल वाचणे अशक्य"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "समावेष करण्याजोगी डेटा प्राप्त करणे अशक्य"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+#| msgid "Error deleting file: %s"
+msgid "Error writing file"
+msgstr "फाइल लिहीतेवेळी त्रुटी आढळली"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+#| msgid "Not a directory"
+msgid "Not supported (not same directory)"
+msgstr "समर्थीत नाही (समान डिरेक्ट्री नाही)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "समर्थीत नाही (src dir आहे, dst dir आहे)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "समर्थीत नाही (src dir आहे, dst अस्तित्वातील फाइल आहे)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "समर्थीत नाही (src फाइल आहे, dst dir आहे)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP क्लाऐंट त्रुटी: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1881
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (अवैध ऐंकोडींग)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "संचयीका सूचना समर्थीत नाही"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows संजाळ"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "संजाळ स्थान नियंत्रण"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s वर %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB समर्थन आढळले नाही. कृपया तुमच्या सॉफ्टवेअर विक्रेताशी संपर्क करा"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "साधनशी जुळवणी तुटली"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "साधानास सॉफ्टवेअर अद्ययावतची आवश्यकता आहे"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh कार्यक्रम अनपेक्षीतरित्या समाप्त झाले"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "यजमाननाव परिचीत नाही"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "यजमान करीता मार्ग नाही"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "सर्वर द्वारे नकारलेली जुळवणी"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "यजमान किल्ली तपास अपयशी"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh कार्याक्रम गुंडाळण्यास अपयशी"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh कार्याक्रम गुंडाळण्यास अपयशी: %s"
+
+#: ../daemon/gvfsbackendsftp.c:525 ../daemon/gvfsbackendsftp.c:777
+msgid "Timed out when logging in"
+msgstr "दाखलन करतेवेळी कालबाह्यता"
+
+#: ../daemon/gvfsbackendsftp.c:855
+msgid "Enter passphrase for key"
+msgstr "किल्ली करीता गुप्तवाक्यरचना प्रविष्ट करा"
+
+#: ../daemon/gvfsbackendsftp.c:857
+msgid "Enter password"
+msgstr "परवलीचा शब्द द्या"
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Can't send password"
+msgstr "परवलीचा शब्द पाठवू शकले नाही"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Log In Anyway"
+msgstr "कसेही करून दाखल करा"
+
+#: ../daemon/gvfsbackendsftp.c:926
+msgid "Cancel Login"
+msgstr "दाखलन रद्द करा"
+
+#: ../daemon/gvfsbackendsftp.c:936
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"दूरस्थ संगणकाची ओळख (%s) अपरिचीत आहे.\n"
+"हे तेव्हा होते जेव्हा तुम्ही संगणकावर दाखलन करता.\n"
+"\n"
+"दूरस्थ संगणकाने पाठविलेली ओळख %s आहे. पुढे जाणे सुरक्षीत आहे हे निश्चित करण्याकरीता, प्रणाली "
+"प्रशासकाशी संपर्क करा."
+
+#: ../daemon/gvfsbackendsftp.c:956
+msgid "Login dialog cancelled"
+msgstr "दाखलन संवाद रद्द केले"
+
+#: ../daemon/gvfsbackendsftp.c:976
+msgid "Can't send host identity confirmation"
+msgstr "यजमान ओळख निश्चितता पाठवू शकत नाही"
+
+#: ../daemon/gvfsbackendsftp.c:1469 ../daemon/gvfsbackendsftp.c:1492
+msgid "Protocol error"
+msgstr "शिष्टाचार त्रुटी"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1517
+#, c-format
+#| msgid "ftp as %s on %s"
+msgid "sftp for %s on %s"
+msgstr "%2$s वरील %1$s करीता sftp करा"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1520
+#, c-format
+msgid "sftp on %s"
+msgstr "%s आढळल्यास sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1546
+msgid "Unable to find supported ssh command"
+msgstr "समर्थीत ssh आदेश शोधण्यास अपयशी"
+
+#: ../daemon/gvfsbackendsftp.c:1966
+msgid "Failure"
+msgstr "अफयशी"
+
+#: ../daemon/gvfsbackendsftp.c:2022 ../daemon/gvfsbackendsftp.c:2101
+#: ../daemon/gvfsbackendsftp.c:2112 ../daemon/gvfsbackendsftp.c:2168
+#: ../daemon/gvfsbackendsftp.c:2254 ../daemon/gvfsbackendsftp.c:2304
+#: ../daemon/gvfsbackendsftp.c:2350 ../daemon/gvfsbackendsftp.c:2425
+#: ../daemon/gvfsbackendsftp.c:2532 ../daemon/gvfsbackendsftp.c:2572
+#: ../daemon/gvfsbackendsftp.c:2622 ../daemon/gvfsbackendsftp.c:2694
+#: ../daemon/gvfsbackendsftp.c:2706 ../daemon/gvfsbackendsftp.c:2764
+#: ../daemon/gvfsbackendsftp.c:2806 ../daemon/gvfsbackendsftp.c:2983
+#: ../daemon/gvfsbackendsftp.c:3008 ../daemon/gvfsbackendsftp.c:3063
+#: ../daemon/gvfsbackendsftp.c:3120 ../daemon/gvfsbackendsftp.c:3391
+#: ../daemon/gvfsbackendsftp.c:3458 ../daemon/gvfsbackendsftp.c:3587
+#: ../daemon/gvfsbackendsftp.c:3622 ../daemon/gvfsbackendsftp.c:3650
+#: ../daemon/gvfsbackendsftp.c:3758 ../daemon/gvfsbackendsftp.c:3812
+#: ../daemon/gvfsbackendsftp.c:3848 ../daemon/gvfsbackendsftp.c:3882
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3912
+#: ../daemon/gvfsbackendsftp.c:3990
+msgid "Invalid reply received"
+msgstr "अवैध प्रतिसाद प्राप्त"
+
+#: ../daemon/gvfsbackendsftp.c:2074
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead अंतर्गत अवैध icon_id '%s' आढळले"
+
+#: ../daemon/gvfsbackendsftp.c:2370
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "प्रतिकृत फाइल बनवितेवेळी त्रुटी: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2868
+msgid "Unable to create temporary file"
+msgstr "तात्पुरती फाइल बनवू शकत नाही"
+
+#: ../daemon/gvfsbackendsftp.c:3684 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "संचयीकेवर संचयीका हलवू शकत नाही"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%2$s वरील साठा %1$s करीता परवलीचा शब्द आवश्यक"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "आंतरीक त्रुटी (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows साठा आरोहीत करण्यास अपयशी"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "असमर्थीत संचयन प्रकार"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "प्रतिकृत फाइल बनविण्यास अपयशी: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "फाइल काढूण टाकतेवेळी त्रुटी: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "फाइल स्थानांतरन करतेवेळी त्रूटी: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "लक्ष्य फाइल काढून टाकतेवेळी त्रूटी: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "संचयीका वारंवाररीत्या काढू शकत नाही"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows सहभागीय फाइलप्रणाली सेवा"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+#| msgid "Password required for share %s on %s"
+msgid "Password required for %s"
+msgstr "%s करीता परवलीचा शब्द आवश्यक"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s वरील Windows साठा"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "सर्वर पासून सहभागीय यादी प्राप्त करण्यास अपयशी"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "फाइल आरोहणजोगी नाही"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "नियमीत फाइल नाही"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows संजाळ फाइलप्रणाली सेवा"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "कचरापेटी फोल्डर नष्ट केले जाऊ शकत नाही"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "कचरापेटी अंतर्गत घटक संपादीत केले जाऊ शकणार नाही"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "कचरापेटी"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "अवैध प्रतिकृत प्रकार"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd पाठवितेवेळी त्रुटी: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "बॅकऐंड द्वारे Symlinks समर्थीत नाही"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "अवैध dbus संदेश"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "जुने डीमन बदलवा."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "फ्युज सुरू करू नका."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS डीमन"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS करीता मुख्य डीमन"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "अधिक माहिती करीता \"%s --help\" वापरू पहा."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "बांधणीतील उपघटकाचे अवैध बाबी"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "स्वआरोहण अपयशी: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "निर्धारीत स्थान आरोहीत नाही"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "निर्धारीत स्थान अनारोहीत नाही"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "स्थान आधिपासूनच आरोहीत आहे"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "स्थान आधिपासूनच आरोहणजोगी नाही"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "सीडी-रॉम डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "रिकामी CD-ROM डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "सीडी-आर डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "रिकामी CD-R डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "रिकामी CD-RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "डिव्हीडी-रॉम डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "रिकामी DVD-ROM डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "डिव्हीडी-रॅम डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "रिकामी डिव्हीडी-रॅम डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "रिकामी DVD-RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "रिकामी DVD+R डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "रिकामी DVD+RW डिस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "रिकामी DVD+R DL डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "रिकामी Blu-Ray डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "रिकामी Blu-Ray R डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "रिकामी Blu-Ray RW डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "रिकामी HD DVD डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "रिकामी HD DVD-R डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "रिकामी HD DVD-RW डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "रिकामी MO डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "डीस्क"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "रिकामी डीस्क"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ड्राइव्ह"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "फ्लॉपी ड्राईव्ह"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "सॉफ्टवेअर RAID ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tape ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "झीप ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "व्यापक संचयन ड्राइव्ह"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "मिडीया बाहेर काढण्यास अपयशी; एक किंवा त्यापेक्षा जास्त मिडीयावरील खंड व्यस्थ आहे."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "मिश्र ऑडिओ/माहिती डीस्क"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s मिडीया"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s कुटलिपीक माहिती"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: फाइल उघडतेवेळी त्रुटी: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout ला लिहीतेवेळी त्रुटी"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: वाचतेवेळी त्रुटी: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:बंद करतेवेळी त्रुट: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "स्थान... - स्थान यांना मानक आउटपुट करीता एकत्र लिहा."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"फाइलला स्थानास एकत्र करा व त्यास मानक आउटपुट करीता छपाई द्या. हे पारंपरीक cat "
+"उपकार्यक्रम सारखेच आहे, पण स्थानीक फाइल ऐवजी gvfs स्थानाचे वापर करते: उदाहरणार्थ तुम्ही "
+"एकत्र करण्याकरीताsmb://server/resource/file.txt स्थान वापरू शकता."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "टिप: स्वरूपण पर्याय जसे की -n, -T किंवा अन्यची आवश्यकता असल्यास त्यास cat शी पाईप करा."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: न आढळलेली स्थान"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: स्थान उघडतेवेळी त्रुटी: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: अनुप्रयोग दाखल करतेवेळी त्रुटी: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "फाइल... - पंजीकृत अनुप्रयोगशी फाइल उघडा."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "फाइल प्रकार हाताळणी करीता पंजीकृत मुलभूत अनुप्रयोगशी फाइल उघडा."
+
diff --git a/trunk/po/nb.po b/trunk/po/nb.po
new file mode 100644
index 00000000..87a8f8ad
--- /dev/null
+++ b/trunk/po/nb.po
@@ -0,0 +1,1627 @@
+# Norwegian translation of gvfs (bokmål dialect).
+# Copyright (C) 1999-2003 Free Software Foundation, Inc.
+# Kjartan Maraas <kmaraas@gnome.org>, 1999-2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 1.1.x\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-10 08:02+0100\n"
+"PO-Revision-Date: 2009-02-10 08:02+0100\n"
+"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
+"Language-Team: Norwegian Bokmål <i18n-nb@lister.ping.uio.no>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operasjonen er ikke støttet. Filer på forskjellige monteringspunkter"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Ugyldig returverdi fra get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Ugyldig returverdi fra query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Kunne ikke finne fildeskriptor for strøm"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Ugyldig returverdi fra open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Fant ikke fildeskriptor for strøm"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Ugyldig returverdi fra kall"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ugyldig returverdi fra get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Kan ikke finne omsluttende montering"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ugyldig filnavn %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ugyldig returverdi fra query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Ugyldig returverdi fra monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Ugyldig returverdi fra monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Operasjonen ble avbrutt"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Feil i protokoll for strøm: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Slutt på strømmen"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Søking ikke støttet på strøm"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Spørreoperasjonen er ikke støttet"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Spørringsinformasjon ikke støttet på strøm"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Feil ved henting av informasjon om monteringspunkt: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Feil ved tilkobling til tjenesten: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Ugyldig returverdi fra open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Feil ved oppretting av plugg: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Feil ved tilkobling til plugg: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Ugyldig format for filinformasjon"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Ugyldig listeinnhold for attributtinformasjon"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Feil ved initiering av Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Feil ved oppretting av Avahi navneoppslag: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Feil i oppslag av «%s» tjeneste «%s» på domene «%s»"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Feil ved oppslag av «%s»-tjeneste «%s» i domene «%s». En eller flere TXT-poster "
+"mangler. Nøkler som kreves: «%s»."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Tidsavbrudd ved oppslag av «%s»-tjeneste «%s» i domene «%s»"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Feilutformet dns-sd encoded_triple «%s»"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "KAn ikke håndtere versjon %d av GVfsIcon-koding"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Feil inndata for GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Feil under tilkobling til D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Filsystemtjeneste for %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Feil: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Bruk %s --spawner dbus-id objekt_sti"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Bruk: %s key=verdi key=verdi..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ingen monteringstype oppgitt"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "monteringspunkt for %s kjører allerede"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "feil under oppstart av monteringstjenesten"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1093
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ på %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1639
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Ingen vertsnavn oppgitt"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Ugyldige monteringsspesifikasjon"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2261 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Filen eksisterer ikke"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1042 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Filen er ikke en katalog"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Brenn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Kan ikke opprette midlertidig katalog"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Filen eller katalogen finnes ikke"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Katalogen er ikke tom"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Kan ikke kopiere fil over katalog"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-oppretting"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Filen eksisterer"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operasjonen ikke tillatt av motoren"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Fil eller katalog finnes ikke i målsti"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Kan ikke kopiere katalog over katalog"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Målfilen eksisterer"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Kan ikke kopiere katalog rekursivt"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Ikke støttet"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Kunne ikke koble til systembussen"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Kan ikke lage libhal-kontekst"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Kan ikke initiere libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Ingen stasjon oppgitt"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Kan ikke finne stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Stasjon %s inneholder ikke lydfiler"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda montert på %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Lyd-plate"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Filsystemet er opptatt: %d åpen fil"
+msgstr[1] "Filsystemet er opptatt: %d åpne filer"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Fil %s finnes ikke på lager %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Feil fra «paranoia» på stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Feil ved søking i strøm på stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Filen finnes ikke"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Filen eksisterer ikke eller er ikke et lydspor"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Filsystemtjeneste for lyd-CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Datamaskin"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Filsystem"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Kan ikke åpne katalog"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Kan ikke åpne monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Intern feil: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Kan ikke montere fil"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Ingen medie i stasjonen"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ikke en monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Kan ikke avmontere fil"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Kan ikke løse ut fil"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-feil: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Kan ikke fortolke svar"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Tomt svar"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Uventet svar fra tjener"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Ugyldig svar"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV-ressurs"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Skriv inn passord for %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Skriv inn passord for proxy"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Ressursen støtter ikke WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV på %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Kan ikke opprette forespørsel"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1859
+#: ../daemon/gvfsbackendftp.c:2525 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Målfilen eksisterer allerede"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Filen er endret eksternt"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Oppretting av sikkerhetskopi feilet"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lokalt nettverk"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Kan ikke overvåke fil eller katalog."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Nettverk"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Kontoer er ikke støttet"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Vert lukket forbindelsen"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Kan ikke åpne dataforbindelse. Kanskje en brannmur forhindrer dette?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Dataforbindelse lukket"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Operasjonen feilet"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Ikke mer plass på tjener"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operasjonen støttes ikke"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Tilgang nektet"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Ukjent sidetype"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2371
+msgid "Invalid filename"
+msgstr "Ugyldig filnavn"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:928
+msgid "Invalid reply"
+msgstr "Ugyldig svar"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "avbrutt overføring"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Kunne ikke koble til vert"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1493
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Skriv inn passord for ftp som %s på %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Skriv inn passord for ftp på %s"
+
+#: ../daemon/gvfsbackendftp.c:1522 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Passorddialog avbrutt"
+
+#: ../daemon/gvfsbackendftp.c:1601
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp på %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1605
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp som %s på %s"
+
+#: ../daemon/gvfsbackendftp.c:1689 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Filen er en katalog"
+
+#: ../daemon/gvfsbackendftp.c:1911 ../daemon/gvfsbackendftp.c:2486
+msgid "backups not supported yet"
+msgstr "sikkerhetskopier er ikke støttet ennå"
+
+#: ../daemon/gvfsbackendftp.c:1988
+msgid "filename too long"
+msgstr "for langt filnavn"
+
+#: ../daemon/gvfsbackendftp.c:2505
+msgid "Invalid destination filename"
+msgstr "Ugyldig filnavn for mål"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Katalog eller fil eksisterer"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Filen eller katalogen finnes ikke"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ugyldig filnavn"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Ikke støttet"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalt kamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s lydspiller"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Lydspiller"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Ingen enhet oppgitt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Kan ikke opprette gphoto2-kontekst"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Feil ved oppretting av kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Feil ved lasting av enhetsinformasjon"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Feil ved oppslag på enhetsinformasjon"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Feil ved henting av enhetsinformasjon"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Feil ved oppsett av kommunikasjonsport for kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Feil ved initiering av kamera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 montert på %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Ingen kamera oppgitt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Feil under oppretting av filobjekt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Feil under henting av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Feil under henting av data fra fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Feilutformet ikonidentifikator «%s»"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Feil ved søking i strøm på kamera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ikke en katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Fikk ikke mappeliste"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Fant ikke filliste"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Feil ved oppretting av katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Navnet eksisterer allerede"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Nytt navn er for langt"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Feil ved endring av navn på katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Feil under endring av navn på fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Katalog «%s» er ikke tom"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Feil under sletting av katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Feil under sletting av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Kan ikke skrive til katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Kan ikke lage ny fil å legge til i"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Kan ikke lese fil for å legge til"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Kan ikke finne data om filen vi skal legge til"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Feil under skriving til fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Ikke støttet (ikke samme katalog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Ikke støttet (kilde er en katalog, mål er en katalog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Ikke støttet (kilde er en katalog, mål er en eksisterende fil)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Ikke støttet (kilde er fil, mål er katalog)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-klientfeil: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ugyldig koding)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Varsling for kataloger er ikke støttet"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows nettverk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Vis nettverkslokasjoner"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s på %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Støtte for USB mangler. Vennligst kontakt din programvareleverandør"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Mistet forbindelsen til enheten"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Enheten krever en programvareoppdatering"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "SSH-program avsluttet uventet"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Vertsnavn ikke kjent"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ingen rute til vert"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Tilkobling nektet av tjener"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Verifisering av vertsnøkkel feilet"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Kan ikke starte SSH-program"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Kan ikke starte ssh-program: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Tidsavbrudd ved innlogging"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Oppgi passord for nøkkel"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Skriv inn passord"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Kunne ikke sende passord"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Logg inn likevel"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Avbryt pålogging"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Ekstern datamaskins identitet (%s) er ukjent.\n"
+"Dette skjer første gang du logger inn på en datamaskin.\n"
+"\n"
+"Identiteten som oversendes av ekstern datamaskin er %s. Kontakt "
+"systemadministrator hvis du vil være helt sikker på at det er trygt å "
+"fortsette."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Påloggingsdialog avbrutt"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Kan ikke sende bekreftelse på vertsidentifikasjon"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Feil i protokoll"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp som %s på %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp på %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Kan ikke finne støttet ssh-kommando"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Feil"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Ugyldig svar mottatt"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Ugyldig icon_id «%s» i OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Feil under oppretting av sikkerhetskopi: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Kan ikke opprette midlertidig fil"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Kan ikke flytte katalog over katalog"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Passord kreves for delt ressurs %s på %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Intern feil (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Klarte ikke å montere Windows-ressurs"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Søketype ikke støttet"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Oppretting av sikkerhetskopi feilet: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Feil under sletting av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Feil under flytting av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Feil under fjerning av målfil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Kan ikke flytte katalog rekursivt"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Filsystemtjeneste for delte Windows-ressurser"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Passord kreves for %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Delt Windows-ressurs på %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Klarte ikke å hente liste over delte ressurser fra tjener"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Filen er ikke monterbar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ikke en vanlig fil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Filsystemtjeneste for Windows nettverk"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Papirkurven kan ikke slettes"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Oppføringer i papirkurven kan ikke endres"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Papirkurv"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ugyldige type motor"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Feil ved sending av fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symbolske lenker er ikke støttet av motoren"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Ugyldig dbus-melding"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Erstatt kjørende tjeneste."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Ikke start fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-tjeneste"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hovedtjeneste for GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Prøv «%s --help» for mer informasjon."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Ugyldige argumenter fra startet underprosess"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatisk montering feilet: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Spesifisert lokasjon er ikke montert"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Spesifisert lokasjon er ikke støttet"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Lokasjonen er allerede montert"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Lokasjonen kan ikke monteres"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM-plate"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tom CD-ROM plate"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tom CD-R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tom CD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM plate"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tom DVD-ROM plate"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM plate"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tom DVD-RAM plate"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tom DVD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tom DVD+R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tom DVD+RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL plate"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tom DVD+R DL plate"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray plate"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tom Blu-Ray plate"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tom Blu-Ray R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tom Blu-Ray RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD plate"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tom HD-DVD plate"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tom HD DVD-R plate"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tom HD DVD-RW plate"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO-plate"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tom MO plate"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tom disk"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-stasjon"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskettstasjon"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Stasjon med programvare-RAID"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-disk"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Firewire-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tape-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Compact Flash-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Minnepinne"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-stasjon"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Tommelstasjon"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Masselagringsenhet"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Klarte ikke å løse ut medie. Ett eller flere volum på mediet er opptatt."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Blandet lyd- og dataplate"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s medie"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s krypterte data"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s feil ved åpning av fil: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, feil ved skriving til stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: feil ved lesing: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: feil ved lukking: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOKASJON... - slå sammen LOKASJONER til standard utdata."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Slå sammen filer ved lokasjoner og skriv ut til standard utdata. Fungerer "
+"som det vanlige cat-verktøyet, men bruker gvfs lokasjoner i stedet for "
+"lokale filer. Du kan for eksempel bruke smb://tjener/ressurs/fil.txt som en "
+"lokasjon som skal vises."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Merk: bare send dette gjennom cat hvis du trenger formateringsalternativene "
+"som -n -T eller annet."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: mangler lokasjoner"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: feil under åpning av lokasjon: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: feil under start av program: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILER... - åpne FILER med registrert program."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Åpner filen(e) med programmet som er registrert som forvalg for å håndtere "
+"denne type fil."
diff --git a/trunk/po/nl.po b/trunk/po/nl.po
new file mode 100644
index 00000000..a00c9c05
--- /dev/null
+++ b/trunk/po/nl.po
@@ -0,0 +1,1667 @@
+# Dutch translation for gvfs
+#
+# This file is distributed under the same license as the gvfs package.
+#
+# Wouter Bolsterlee <wbolster@gnome.org>, 2008–2009
+#
+# LET OP! Wouter wil graag de controle over dit bestand houden. Neem
+# a.u.b. eerst even contact op voordat je wijzigingen doorvoert.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-14 01:24+0100\n"
+"PO-Revision-Date: 2009-02-04 12:14+0100\n"
+"Last-Translator: Wouter Bolsterlee <wbolster@gnome.org>\n"
+"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Bewerking niet ondersteund; bestanden op verschillende koppelpunten"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Ongeldig resultaat van ‘get_info’"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Ongeldig resultaat van ‘query_info’"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Kon ‘stream file descriptor’ niet verkrijgen"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Ongeldig resultaat van ‘open’"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Kon ‘stream file descriptor’ niet verkrijgen"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Ongeldig resultaat van aanroep"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ongeldig resultaat van ‘get_filesystem_info’"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Kon omvattend koppelpunt niet vinden"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ongeldige bestandsnaam: ‘%s’"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ongeldig resultaat van ‘query_filesystem_info’"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Ongeldig resultaat van ‘monitor_dir’"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Ongeldig resultaat van ‘monitor_file’"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Bewerking is geannuleerd"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Fout in stream-protocol: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Einde van stream"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Zoeken in stream niet ondersteund"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Bewerking voor opvragen van informatie wordt niet ondersteund"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Opvragen van informatie van stream niet ondersteund"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Kon koppelingsinfo niet verkrijgen: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Fout bij verbinden naar voorziening: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Ongeldige resultaatwaarde van ‘open_icon_for_read’"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Fout bij maken van socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Fout bij verbinden met socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Ongeldig formaat bestandsinformatie"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Ongeldige inhoud in eigenschappenlijst"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Fout bij initialiseren van Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Fout bij maken van Avahi-resolver: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Fout bij resolven van ‘%s’-service ‘%s’ in domein ‘%s’"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Fout bij resolven van ‘%s’-service ‘%s’ in domein ‘%s’. Een of meerdere TXT-"
+"records ontbreken. Benodigde keys: ‘%s’."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Timeout bij resolven van ‘%s’-service ‘%s’ in domein ‘%s’"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Ongeldige ‘dns-sd encoded_triple’: ‘%s’"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Kan versie %d van GVfsIcon-codering niet verwerken"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Ongeldige invoergegevens voor GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Fout bij verbinden met D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Bestandssysteemvoorziening voor %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Fout: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Gebruik: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Gebruik: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Geen koppeltype opgegeven"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "koppelpunt voor %s reeds actief"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "fout bij starten van koppelvoorziening"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ op %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Geen hostnaam opgegeven"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Ongeldige aankoppelspecificatie"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Bestand bestaat niet"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Het bestand is geen map"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Branden"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Kon tijdelijke map niet aanmaken"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Bestand of map bestaat niet"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Map is niet leeg"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Kan bestand niet over map heen kopiëren"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Cd/dvd branden"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Bestand bestaat al"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Bewerking niet door backend ondersteund"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Bestand of map niet in doelmap gevonden"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Kan map niet over map heen kopiëren"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Doelbestand bestaat al"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Kan map niet recursief kopiëren"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Niet ondersteund"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Kon niet met ‘system bus’ verbinden"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Kon libhal-context niet aanmaken"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Kon libhal niet initialiseren"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Geen station opgegeven"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Can station %s niet vinden"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Station %s bevat geen audiobestanden"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda-koppeling op %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Audio-cd"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Bestandssysteem is bezig: %d open bestand"
+msgstr[1] "Bestandssysteem is bezig: %d open bestanden"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Geen bestand %s op station %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Fout van ‘paranoia’ op station %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Fout bij zoeken in stream op station %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Bestand bestaat niet"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Het bestand bestaat niet of is geen muziekbestand"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Bestandssysteemvoorziening voor audio-cd's"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Bestandssysteem"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Kan map niet openen"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Kan aankoppelbaar bestand niet openen"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Interne fout: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Kan bestand niet aankoppelen"
+
+# Vrij vertaald (Wouter Bolsterlee)
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Geen media in schijf of lade"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Geen aankoppelbaar bestand"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Kan bestand niet ontkoppelen"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Kan bestand niet uitwerpen"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-fout: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Kan antwoord niet verwerken"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Leeg antwoord"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Onverwacht antwoord van server"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Ongeldig antwoord"
+
+# Vrij vertaald (Wouter Bolsterlee)
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV-map"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Voer wachtwoord voor %s in"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Voer uw proxy-wachtwoord in"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Geen WebDAV-schijf"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV op %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Kon aanvraag niet aanmaken"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Doelbestand bestaat al"
+
+# Vrij vertaald (Wouter Bolsterlee)
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Het bestand is tussentijds gewijzigd"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Aanmaken reservekopie"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lokaal netwerk"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Kan bestand of map niet monitoren."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Netwerk"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Accounts worden niet ondersteund"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "De host heeft de verbinding verbroken"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Kan dataverbinding niet openen. Wellicht blokkeert uw firewall dit."
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Dataverbinding gesloten"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Bewerking is mislukt"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Geen vrije ruimte meer op server"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Bewerking niet ondersteund"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Toegang geweiger"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Paginatype onbekend"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Ongeldige bestandsnaam"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Ongeldig antwoord"
+
+# Vrij vertaald (Wouter Bolsterlee)
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "verzenden mislukt"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Kon niet met host verbinden"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Voer wachtwoord voor ftp voor %s op %s in"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Voer wachtwoord voor ftp op %s in"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Wachtwoordvenster geannuleerd"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp op %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp voor %s op %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Bestand is een map"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "backups (nog) niet ondersteund"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "bestandsnaam te lang"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Ongeldige doelbestandsnaam"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Bestand of map bestaat al"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Bestand of map bestaat niet"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ongeldige bestandsnaam"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Niet ondersteund"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitale camera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s-camera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s-muziekspeler"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Camera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Muziekspeler"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Geen apparaat opgegeven"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Kon gphoto2-context niet aanmaken"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Kon camera niet aanmaken"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Fout bij opvragen van apparaatinformatie"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Fout bij opvragen van apparaatinformatie"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Fout bij verkrijgen van apparaatinformatie"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Instellen communicatiepoort voor camera mislukt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Fout bij initialiseren camera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2-koppeling op %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Geen camera opgegeven"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Fout bij aanmaken bestandobject"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Fout bij ophalen bestand"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Fout bij verkrijgen data van bestand"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Ongeldige pictogram-identifier ‘%s’"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Fout bij zoeken in stream op camera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Geen map"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Opvragen van mappenlijst mislukt"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Opvragen van bestandenlijst mislukt"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Fout bij aanmaken van map"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Naam bestaat al"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Nieuwe naam te lang"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Fout bij hernoemen van map"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Fout bij hernoemen van bestand"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Map ‘%s’ is niet leeg"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Fout bij verwijderen van map"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Fout bij verwijderen van bestand"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Kan niet in map schrijven"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Kan geen nieuw bestand om naar te schrijven aanmaken"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Kan bestand om naar te schrijven niet lezen"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Kan data in bestand om naar te schrijven niet opvragen"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Fout bij schrijven van bestand"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Niet ondersteund (niet dezelfde map)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Niet ondersteund (bron is map, doel is map)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Niet ondersteund (bron is map, doel is bestaand bestand)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Niet ondersteund (bron is bestand, doel is map)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-clientfout: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ongeldige codering)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Mapwijzigingsmeldingen niet ondersteund"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows-netwerk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor voor netwerklokaties"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s op %s"
+
+# Vrij vertaald (Wouter Bolsterlee)
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB-ondersteuning ontbreekt. Neem contact op met uw beheerder."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Verbinding met apparaat verloren"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Het apparaat heeft een software-update nodig"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "SSH-programma werd onverwacht afgesloten"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Hostnaam onbekend"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Geen route naar host"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Verbinding geweigerd door server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Controle van hostsleutel mislukt"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Kon SSH-programma niet starten"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Kon SSH-programma niet starten: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Wachttijd voor aanmelden overschreven"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Voer wachtwoordzin voor sleutel in"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Voer wachtwoord in"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Kon wachtwoord niet zenden"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Toch aanmelden"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Aanmelden annuleren"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"De identiteit van de computer op afstand (%s) is onbekend.\n"
+"Dit gebeurt wanneer u zich voor de eerste keer bij een computer aanmeldt.\n"
+"\n"
+"De identiteit die door de computer op afstand is verzonden is %s. Indien u "
+"absoluut zeker wilt weten of het veilig is om door te gaan, neem dan contact "
+"op met de systeembeheerder."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Aanmeldvenster geannuleerd"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Kan informatie over host-identiteit niet zenden"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protocolfout"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp voor %s op %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp op %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Kon geen ondersteund SSH-programma vinden"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Mislukt"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Ongeldig antwoord ontvangen"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Ongeldig icon_id ‘%s’ in OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Fout bij maken reservekopie: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Kon tijdelijk bestand niet maken"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Kan map niet over andere map heen verplaatsen"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Wachtwoord benodigd voor gedeelde map %s op %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Interne fout (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Kon gedeelde Windows-map niet aankoppelen"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Niet ondersteund zoektype"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Kon reservekopiebestand niet maken: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Fout bij verwijderen van bestand: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Fout bij verplaatsen van bestand: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Fout bij verwijderen doelbestand: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Kan map niet recursief verplaatsen"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Bestandssysteemvoorziening voor gedeelde Windows-mappen"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Wachtwoord benodigd voor %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Gedeelde Windows-mappen op %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Kon lijst van gedeelde mappen niet van server opvragen"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Het bestand is niet aankoppelbaar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Geen normaal bestand"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Bestandssysteemvoorziening voor Windows-netwerken"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "De prullenbak kan niet verwijderd worden"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Items in de prullenbak kunnen niet gewijzigd worden"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Prullenbak"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ongeldig backend-type"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Fout bij zenden naar ‘file descriptor’: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symbolische verwijzingen niet door backend ondersteund"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Ongeldig D-Bus-bericht"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Oude voorziending vervangen."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Fuse niet starten."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-voorziening"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hoofdvoorziening voor GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Probeer ‘%s --help’ voor meer informatie."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Ongeldige parameters van opgestart dochterproces"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Auto-aankoppelen mislukt: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "De opgegeven locatie is niet aangekoppeld"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "De opgegeven locatie wordt niet ondersteund"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Locatie is reeds aangekoppeld"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Locatie is niet aankoppelbaar"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Cd-rom-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Lege cd-rom-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Cd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Lege cd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Cd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Lege cd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Dvd-rom-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Lege dvd-rom-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Dvd-ram-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Lege dvd-ram-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Dvd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Lege dvd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Dvd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Lege dvd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Dvd+rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Lege dvd+rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Dvd+r DL-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Lege dvd+r dl-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-ray-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Lege Blu-ray-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-ray-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Lege Blu-ray-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-ray-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Lege Blu-ray-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Hd-dvd-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Lege hd-dvd-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Hd-dvd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Lege hd-dvd-r-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Hd-dvd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Lege hd-dvd-rw-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Lege MO-schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Schijf"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Lege schijf"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "Cd-rom"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "Cd-r"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "Cd-rw"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "Dvd-rom"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "Dvd+r"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "Dvd+rw"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "Dvd-r"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "Dvd-rw"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "Dvd-ram"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "Dvd±r"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "Dvd±rw"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "Hd-dvd"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "Hd-dvd-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "Hd-dvd-rw"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-station"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-station"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskettestation"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Software RAID-schijf"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-schijf"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-schijf"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-schijf"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire-schijf"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tape-station"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-station"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-station"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-station"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-station"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-station"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-station"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb-station"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Opslagstation"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Kon media niet uitwerpen; een of meerdere volumina zijn bezig."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Schijf met audio en data"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Media van %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s versleutelde gegevens"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: fout bij openen van bestand: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, schrijffout op ‘stdout’"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: leesfout: %s\n"
+
+# Er moet een spatie in het origineel bij (Wouter Bolsterlee)
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: fout bij sluiten: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATIE… - LOCATIES achter elkaar weergeven op standaarduitvoer"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Bestanden op bepaalde locaties achter elkaar weergeven en op de "
+"standaarduitvoer tonen. Dit werkt net als het ‘cat’-programma, maar gebruikt "
+"gvfs-locaties in plaats van lokale bestanden. U kunt bijvoorbeeld iets als "
+"‘smb://server/map/naar/bestand.txt’ gebruiken als locatie."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Let op: gebruik een ‘pipe’ als u opmaakopties zoals ‘-n’ of ‘-T’ wilt "
+"gebruiken."
+
+# Vrij vertaald (Wouter Bolsterlee)
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: locatie ontbreekt"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: fout bij openen locatie: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: fout bij opstarten van toepassing: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "BESTANDEN… — BESTANDEN openen met standaardtoepassing."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Een of meerdere bestanden met de standaardtoepassing voor dit bestandstype "
+"openen."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Kan prullenbak niet legen"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (in prullenbak)"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Prullenbakwijzigingsmeldingen niet ondersteund"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Fout bij opvragen van mappen"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "Bestandssysteem is bezig: %d geopende bestanden"
+
+#~ msgid "File unavailable"
+#~ msgstr "Bestand niet beschikbaar"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Media van %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Media van %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Media van %.1f GB"
+
+#~ msgid "Invalid reply from server."
+#~ msgstr "Ongeldig antwoord ontvangen van server."
diff --git a/trunk/po/nn.po b/trunk/po/nn.po
new file mode 100644
index 00000000..055c08c8
--- /dev/null
+++ b/trunk/po/nn.po
@@ -0,0 +1,1350 @@
+# Norwegian translation of gvfs (nynorsk dialect).
+# Copyright (C) 1999-2003 Free Software Foundation, Inc.
+# Kjartan Maraas <kmaraas@gnome.org>, 1999-2008.
+# Eskild Hustvedt <eskildh@gnome.org>, 2008
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 0.1.x\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-09 15:18+0100\n"
+"PO-Revision-Date: 2008-03-31 10:17+0200\n"
+"Last-Translator: Eskild Hustvedt <eskildh@gnome.org>\n"
+"Language-Team: Norwegian nynorsk <i18n-no@lister.ping.uio.no>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:464 ../client/gdaemonfile.c:1867
+msgid "Operation not supported, files on different mounts"
+msgstr "Operasjonen er ikkje støtta. Filer på ulike monteringspunkt"
+
+#: ../client/gdaemonfile.c:758
+msgid "Invalid return value from get_info"
+msgstr "Ugyldig returverdi frå get_info"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from query_info"
+msgstr "Ugyldig returverdi frå query_info"
+
+#: ../client/gdaemonfile.c:865
+msgid "Couldn't get stream file descriptor"
+msgstr "Kunne ikkje finna fildeskriptor for straum"
+
+#: ../client/gdaemonfile.c:897 ../client/gdaemonfile.c:967
+#: ../client/gdaemonfile.c:1026 ../client/gdaemonfile.c:1085
+#: ../client/gdaemonfile.c:1147
+msgid "Invalid return value from open"
+msgstr "Ugyldig returverdi frå open"
+
+#: ../client/gdaemonfile.c:977 ../client/gdaemonfile.c:1036
+#: ../client/gdaemonfile.c:1095 ../client/gdaemonfile.c:1157
+msgid "Didn't get stream file descriptor"
+msgstr "Fann ikkje fildeskriptor for straum"
+
+#: ../client/gdaemonfile.c:1209 ../client/gdaemonfile.c:1226
+msgid "Invalid return value from call"
+msgstr "Ugyldig returverdi frå kall"
+
+#: ../client/gdaemonfile.c:1505
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ugyldig returverdi frå get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1549
+msgid "Could not find enclosing mount"
+msgstr "Kan ikkje finna omsluttende montering"
+
+#: ../client/gdaemonfile.c:1579
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ugyldig filnamn %s"
+
+#: ../client/gdaemonfile.c:1621
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ugyldig returverdi frå query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2012
+msgid "Invalid return value from monitor_dir"
+msgstr "Ugyldig returverdi frå monitor_dir"
+
+#: ../client/gdaemonfile.c:2061
+msgid "Invalid return value from monitor_file"
+msgstr "Ugyldig returverdi frå monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:451
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1304
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:403
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../client/gdaemonfileoutputstream.c:1062
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Feil i protokoll for straum: %s"
+
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1062
+msgid "End of stream"
+msgstr "Slutt på straummen"
+
+#: ../client/gdaemonfileinputstream.c:519
+#: ../client/gdaemonfileinputstream.c:676
+#: ../client/gdaemonfileinputstream.c:785
+#: ../client/gdaemonfileinputstream.c:1036
+#: ../client/gdaemonfileoutputstream.c:460
+#: ../client/gdaemonfileoutputstream.c:639
+#: ../client/gdaemonfileoutputstream.c:835 ../daemon/gvfsbackendobexftp.c:774
+#: ../daemon/gvfsbackendobexftp.c:795 ../daemon/gvfsbackendobexftp.c:914
+#: ../daemon/gvfsbackendobexftp.c:1051 ../daemon/gvfsbackendobexftp.c:1115
+#: ../daemon/gvfsbackendobexftp.c:1252 ../daemon/gvfsbackendobexftp.c:1279
+#: ../daemon/gvfsbackendobexftp.c:1338 ../daemon/gvfsbackendobexftp.c:1360
+#: ../daemon/gvfsbackendobexftp.c:1420 ../daemon/gvfsbackendobexftp.c:1439
+#: ../daemon/gvfsbackendsmb.c:1015 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:297
+msgid "Operation was cancelled"
+msgstr "Operasjonen vart avbrota"
+
+#: ../client/gdaemonfileinputstream.c:1211
+#: ../client/gdaemonfileoutputstream.c:946
+msgid "Seek not supported on stream"
+msgstr "Søking ikkje støtta på straum"
+
+#: ../client/gdaemonfileinputstream.c:1241
+msgid "The query info operation is not supported"
+msgstr "Spørreoperasjonen er ikkje støtta"
+
+#: ../client/gdaemonvfs.c:731
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Feil ved henting av informasjon om monteringspunkt: %s"
+
+#: ../client/gvfsdaemondbus.c:559 ../client/gvfsdaemondbus.c:946
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Feil ved tilkopling til tenesten: %s"
+
+#: ../common/gsysutils.c:133
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Feil ved oppretting av plugg: %s"
+
+#: ../common/gsysutils.c:171
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Feil ved tilkopling til plugg: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Ugyldig format for filinformasjon"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "Ugyldig listeinnhald for attributtinformasjon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Feil under tilkopling til D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Filsystemteneste for %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Feil: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Bruk %s --spawner dbus-id objekt_stig"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Bruk: %s key=verdi key=verdi ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Inga monteringstype oppgjeven"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "monteringspunkt for %s køyrer allereie"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "feil under oppstart av monteringstenesten"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:347
+msgid "Burn"
+msgstr "Brenn"
+
+#: ../daemon/gvfsbackendburn.c:377
+msgid "Unable to create temporary directory"
+msgstr "Kan ikkje oppretta mellombels mappe"
+
+#: ../daemon/gvfsbackendburn.c:406 ../daemon/gvfsbackendburn.c:417
+#: ../daemon/gvfsbackendburn.c:452 ../daemon/gvfsbackendburn.c:673
+#: ../daemon/gvfsbackendburn.c:720 ../daemon/gvfsbackendburn.c:746
+#: ../daemon/gvfsbackendburn.c:784
+msgid "No such file or directory"
+msgstr "Fila eller mappa finst ikkje"
+
+#: ../daemon/gvfsbackendburn.c:426 ../daemon/gvfsbackenddav.c:1804
+msgid "Directory not empty"
+msgstr "Mappa er ikkje tom"
+
+#: ../daemon/gvfsbackendburn.c:460 ../daemon/gvfsbackendburn.c:898
+msgid "Can't copy file over directory"
+msgstr "Kan ikkje kopiere fil over mappe"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:652
+msgid "CD/DVD Creator"
+msgstr "CD/DVD-oppretting"
+
+#: ../daemon/gvfsbackendburn.c:681 ../daemon/gvfsbackendcomputer.c:652
+#: ../daemon/gvfsbackenddnssd.c:393 ../daemon/gvfsbackendftp.c:846
+#: ../daemon/gvfsbackendnetwork.c:637
+#, c-format
+msgid "The file is not a directory"
+msgstr "Fila er ikkje ei mappe"
+
+#: ../daemon/gvfsbackendburn.c:756 ../daemon/gvfsbackendburn.c:792
+#: ../daemon/gvfsbackendburn.c:918
+msgid "File exists"
+msgstr "Fila eksisterer"
+
+#: ../daemon/gvfsbackendburn.c:846
+msgid "No such file or directory in target path"
+msgstr "Fil eller mappe finst ikkje i målstig"
+
+#: ../daemon/gvfsbackendburn.c:869
+msgid "Can't copy directory over directory"
+msgstr "Kan ikkje kopiere mappe over mappe"
+
+#: ../daemon/gvfsbackendburn.c:878
+msgid "Target file exists"
+msgstr "Målfila eksisterer"
+
+#: ../daemon/gvfsbackendburn.c:885
+msgid "Can't recursively copy directory"
+msgstr "Kan ikkje kopiere mappe rekursivt"
+
+#: ../daemon/gvfsbackendburn.c:944
+msgid "Not supported"
+msgstr "Ikkje støtta"
+
+#: ../daemon/gvfsbackendcdda.c:264 ../daemon/gvfsbackendcdda.c:335
+msgid "No drive specified"
+msgstr "Inga stasjon oppgjeven"
+
+#: ../daemon/gvfsbackendcdda.c:279
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Kan ikkje finna stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:289
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Stasjon %s inneheld ikkje lydfiler"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:297
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda montert på %s"
+
+#: ../daemon/gvfsbackendcdda.c:298 ../daemon/gvfsbackendcdda.c:802
+#: ../hal/ghalmount.c:492 ../hal/ghalvolume.c:299 ../hal/ghalvolume.c:320
+#, c-format
+msgid "Audio Disc"
+msgstr "Lyd-plate"
+
+#: ../daemon/gvfsbackendcdda.c:359
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Filsystemet er opptatt: %d open fil"
+msgstr[1] "Filsystemet er opptatt: %d opna filer"
+
+#: ../daemon/gvfsbackendcdda.c:549
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Fil %s finst ikkje på lagar %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:658
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Feil frå «paranoia» på stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:721
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Feil ved søking i straum på stasjon %s"
+
+#: ../daemon/gvfsbackendcdda.c:818 ../daemon/gvfsbackendgphoto2.c:1695
+#, c-format
+msgid "No such file"
+msgstr "Fila finst ikkje"
+
+#: ../daemon/gvfsbackendcdda.c:825 ../daemon/gvfsbackendcomputer.c:573
+#: ../daemon/gvfsbackenddnssd.c:345 ../daemon/gvfsbackendftp.c:1956
+#: ../daemon/gvfsbackendnetwork.c:590 ../daemon/gvfsbackendsmbbrowse.c:799
+#: ../daemon/gvfsbackendsmbbrowse.c:866 ../daemon/gvfsbackendsmbbrowse.c:1037
+#: ../daemon/gvfsbackendsmbbrowse.c:1111
+#, c-format
+msgid "File doesn't exist"
+msgstr "Fila eksisterer ikkje"
+
+#: ../daemon/gvfsbackendcdda.c:832
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Fila eksisterer ikkje eller er ikkje eit lydspor"
+
+#: ../daemon/gvfsbackendcdda.c:938
+msgid "Audio CD Filesystem Service"
+msgstr "Filsystemteneste for lyd-CD"
+
+#: ../daemon/gvfsbackendcomputer.c:180 ../daemon/gvfsbackendcomputer.c:694
+msgid "Computer"
+msgstr "Datamaskin"
+
+#: ../daemon/gvfsbackendcomputer.c:467
+msgid "Filesystem"
+msgstr "Filsystem"
+
+#: ../daemon/gvfsbackendcomputer.c:591 ../daemon/gvfsbackendgphoto2.c:1687
+#: ../daemon/gvfsbackendobexftp.c:760 ../daemon/gvfsbackendtrash.c:638
+msgid "Can't open directory"
+msgstr "Kan ikkje opna mappe"
+
+#: ../daemon/gvfsbackendcomputer.c:595 ../daemon/gvfsbackendcomputer.c:733
+msgid "Can't open mountable file"
+msgstr "Kan ikkje opna monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:781
+#, c-format
+msgid "Internal error: %s"
+msgstr "Intern feil: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:813 ../daemon/gvfsbackendcomputer.c:930
+msgid "Can't mount file"
+msgstr "Kan ikkje montere fil"
+
+#: ../daemon/gvfsbackendcomputer.c:825
+msgid "No media in the drive"
+msgstr "Inga medie i stasjonen"
+
+#: ../daemon/gvfsbackendcomputer.c:882 ../daemon/gvfsbackendcomputer.c:973
+#: ../daemon/gvfsbackendcomputer.c:1073
+msgid "Not a mountable file"
+msgstr "Ikkje ein monterbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:988
+msgid "Can't unmount file"
+msgstr "Kan ikkje avmontere fil"
+
+#: ../daemon/gvfsbackendcomputer.c:1104
+msgid "Can't eject file"
+msgstr "Kan ikkje lause ut fil"
+
+#: ../daemon/gvfsbackenddav.c:269 ../daemon/gvfsbackenddav.c:1289
+#: ../daemon/gvfsbackendhttp.c:220
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-feil: %s"
+
+#: ../daemon/gvfsbackenddav.c:285
+msgid "Could not parse response"
+msgstr "Kan ikkje fortolke svar"
+
+#: ../daemon/gvfsbackenddav.c:294
+msgid "Empty response"
+msgstr "Tomt svar"
+
+#: ../daemon/gvfsbackenddav.c:301
+msgid "Unexpected reply from server"
+msgstr "Uventet svar frå tenar"
+
+#: ../daemon/gvfsbackenddav.c:944 ../daemon/gvfsbackenddav.c:1421
+#, c-format
+msgid "Response invalid"
+msgstr "Ugyldig svar"
+
+#: ../daemon/gvfsbackenddav.c:1087
+msgid "WebDAV share"
+msgstr "WebDAV-ressurs"
+
+#: ../daemon/gvfsbackenddav.c:1089
+#, c-format
+msgid "Enter password for %s"
+msgstr "Skriv inn passord for %s"
+
+#: ../daemon/gvfsbackenddav.c:1092
+msgid "Please enter proxy password"
+msgstr "Skriv inn passord for mellomtenar"
+
+#: ../daemon/gvfsbackenddav.c:1206 ../daemon/gvfsbackendhttp.c:273
+#: ../daemon/gvfsbackendobexftp.c:605 ../daemon/gvfsbackendobexftp.c:616
+#: ../daemon/gvfsbackendsmb.c:595
+msgid "Invalid mount spec"
+msgstr "Ugyldige monteringsspesifikasjon"
+
+#: ../daemon/gvfsbackenddav.c:1293 ../daemon/gvfsbackenddav.c:1297
+msgid "Not a WebDAV enabled share"
+msgstr "Ressursen støttar ikkje WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1319
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV på %s"
+
+#: ../daemon/gvfsbackenddav.c:1377 ../daemon/gvfsbackenddav.c:1448
+msgid "Could not create request"
+msgstr "Kan ikkje oppretta førespurnad"
+
+#: ../daemon/gvfsbackenddav.c:1511 ../daemon/gvfsbackenddav.c:1764
+#: ../daemon/gvfsbackendftp.c:1559 ../daemon/gvfsbackendftp.c:2190
+#: ../daemon/gvfsbackendsmb.c:1701
+#, c-format
+msgid "Target file already exists"
+msgstr "Målfila eksisterer allereie"
+
+#: ../daemon/gvfsbackenddav.c:1584 ../daemon/gvfsbackendsftp.c:2662
+#: ../daemon/gvfsbackendsmb.c:983
+msgid "The file was externally modified"
+msgstr "Fila er endra eksternt"
+
+#: ../daemon/gvfsbackenddav.c:1615 ../daemon/gvfsbackendsmb.c:1021
+#: ../daemon/gvfsbackendsmb.c:1718
+msgid "Backup file creation failed"
+msgstr "Oppretting av sikkerhetskopi mislukkast"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Kan ikkje overvåke fil eller mappe."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Nettverk"
+
+#: ../daemon/gvfsbackendftp.c:224
+msgid "Accounts are unsupported"
+msgstr "Kontoer er ikkje støtta"
+
+#: ../daemon/gvfsbackendftp.c:228
+msgid "Host closed connection"
+msgstr "Vert lukka forbindelsen"
+
+#: ../daemon/gvfsbackendftp.c:232
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Kan ikkje opna datasamband. Kanskje ein brannmur forhindrer dette?"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Data connection closed"
+msgstr "Datasamband lukka"
+
+#: ../daemon/gvfsbackendftp.c:242
+msgid "File unavailable"
+msgstr "Fila er ikkje tilgjengeleg"
+
+#: ../daemon/gvfsbackendftp.c:246
+msgid "Operation failed"
+msgstr "Operasjonen mislukkast"
+
+#: ../daemon/gvfsbackendftp.c:251
+msgid "No space left on server"
+msgstr "Ikkje meir plass på tenar"
+
+#: ../daemon/gvfsbackendftp.c:259 ../daemon/gvfsbackendsftp.c:3685
+msgid "Operation unsupported"
+msgstr "Operasjonen støttes ikkje"
+
+#: ../daemon/gvfsbackendftp.c:263 ../daemon/gvfsbackendsftp.c:259
+msgid "Permission denied"
+msgstr "Tilgang nekta"
+
+#: ../daemon/gvfsbackendftp.c:267
+msgid "Page type unknown"
+msgstr "Ukjend sidetype"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:2060
+#, c-format
+msgid "Invalid filename"
+msgstr "Ugyldig filnamn"
+
+#: ../daemon/gvfsbackendftp.c:275 ../daemon/gvfsbackendftp.c:349
+#: ../daemon/gvfsbackendftp.c:378 ../daemon/gvfsbackendftp.c:397
+#: ../daemon/gvfsbackendftp.c:410 ../daemon/gvfsbackendftp.c:751
+#, c-format
+msgid "Invalid reply"
+msgstr "Ugyldig svar"
+
+#: ../daemon/gvfsbackendftp.c:517
+#, c-format
+msgid "broken transmission"
+msgstr "avbrota overføring"
+
+#: ../daemon/gvfsbackendftp.c:611 ../daemon/gvfsbackendftp.c:771
+#, c-format
+msgid "Could not connect to host"
+msgstr "Kunne ikkje kopla til vert"
+
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendftp.c:897 ../daemon/gvfsbackendsftp.c:1736
+#, c-format
+msgid "/ on %s"
+msgstr "/ på %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1259
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Skriv inn passord for ftp på %s"
+
+#: ../daemon/gvfsbackendftp.c:1279 ../daemon/gvfsbackendsftp.c:833
+msgid "Password dialog cancelled"
+msgstr "Passorddialog avbrota"
+
+#: ../daemon/gvfsbackendftp.c:1345
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp på %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1351
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp som %s på %s"
+
+#: ../daemon/gvfsbackendftp.c:1385 ../daemon/gvfsbackendsftp.c:1410
+msgid "No hostname specified"
+msgstr "Inga vertsnamn oppgjeven"
+
+#: ../daemon/gvfsbackendftp.c:1609 ../daemon/gvfsbackendftp.c:2151
+msgid "backups not supported yet"
+msgstr "sikkerhetskopier er ikkje støtta ennå"
+
+#: ../daemon/gvfsbackendftp.c:1685
+#, c-format
+msgid "filename too long"
+msgstr "for langt filnamn"
+
+#: ../daemon/gvfsbackendftp.c:2170
+#, c-format
+msgid "Invalid destination filename"
+msgstr "Ugyldig filnamn for mål"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:697
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalt kamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:843 ../hal/ghalvolume.c:399
+#, c-format
+msgid "%s Camera"
+msgstr "%s kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:846 ../hal/ghalvolume.c:394
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s lydspelar"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../hal/ghalvolume.c:408
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:857 ../hal/ghalvolume.c:406
+msgid "Audio Player"
+msgstr "Lydspelar"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1539
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 montert på %s"
+
+#: ../daemon/gvfsbackendhttp.c:216
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-klientfeil: %s"
+
+#: ../daemon/gvfsbackendhttp.c:534 ../daemon/gvfsbackendsftp.c:1724
+#: ../daemon/gvfsbackendsmb.c:1230 ../daemon/gvfsbackendtrash.c:963
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ugyldig koding)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Varsling for kataloger er ikkje støtta"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:694
+msgid "Windows Network"
+msgstr "Windows nettverk"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Lokalt nettverk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Vis nettverkslokasjonar"
+
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:444 ../daemon/gvfsbackendsmb.c:514
+#: ../daemon/gvfsbackendsmb.c:1223
+#, c-format
+msgid "%s on %s"
+msgstr "%s på %s"
+
+#: ../daemon/gvfsbackendsftp.c:251
+msgid "ssh program unexpectedly exited"
+msgstr "SSH-program avslutta uventet"
+
+#: ../daemon/gvfsbackendsftp.c:266
+msgid "Hostname not known"
+msgstr "Vertsnamn ikkje kjent"
+
+#: ../daemon/gvfsbackendsftp.c:273
+msgid "No route to host"
+msgstr "Inga rute til vert"
+
+#: ../daemon/gvfsbackendsftp.c:280
+msgid "Connection refused by server"
+msgstr "Tilkopling nekta av tenar"
+
+#: ../daemon/gvfsbackendsftp.c:287
+msgid "Host key verification failed"
+msgstr "Verifisering av vertsnøkkel mislukkast"
+
+#: ../daemon/gvfsbackendsftp.c:370
+msgid "Unable to spawn ssh program"
+msgstr "Kan ikkje starta SSH-program"
+
+#: ../daemon/gvfsbackendsftp.c:386
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Kan ikkje starta ssh-program: %s"
+
+#: ../daemon/gvfsbackendsftp.c:489 ../daemon/gvfsbackendsftp.c:741
+msgid "Timed out when logging in"
+msgstr "Tidsavbrudd ved innlogging"
+
+#: ../daemon/gvfsbackendsftp.c:817
+msgid "Enter passphrase for key"
+msgstr "Oppgi passord for nøkkel"
+
+#: ../daemon/gvfsbackendsftp.c:819
+msgid "Enter password"
+msgstr "Skriv inn passord"
+
+#: ../daemon/gvfsbackendsftp.c:880
+msgid "Can't send password"
+msgstr "Kunne ikkje sende passord"
+
+#: ../daemon/gvfsbackendsftp.c:888
+msgid "Log In Anyway"
+msgstr "Logg inn likevel"
+
+#: ../daemon/gvfsbackendsftp.c:888
+msgid "Cancel Login"
+msgstr "Avbryt pålogging"
+
+#: ../daemon/gvfsbackendsftp.c:898
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Ekstern datamaskins identitet (%s) er ukjend.\n"
+"Dette skjer første gong du logger inn på ein datamaskin.\n"
+"\n"
+"Identiteten som oversendes av ekstern datamaskin er %s. Kontakt systemadministrator viss du vil vera helt sikker på at det er trygt å halda fram."
+
+#: ../daemon/gvfsbackendsftp.c:918
+msgid "Login dialog cancelled"
+msgstr "Påloggingsdialog avbrota"
+
+#: ../daemon/gvfsbackendsftp.c:938
+msgid "Can't send host identity confirmation"
+msgstr "Kan ikkje sende bekreftelse på vertsidentifikasjon"
+
+#: ../daemon/gvfsbackendsftp.c:1329 ../daemon/gvfsbackendsftp.c:1352
+msgid "Protocol error"
+msgstr "Feil i protokoll"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1376
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp på %s"
+
+#: ../daemon/gvfsbackendsftp.c:1400
+msgid "Unable to find supported ssh command"
+msgstr "Kan ikkje finna støtta ssh-kommando"
+
+#: ../daemon/gvfsbackendsftp.c:1800
+msgid "File is directory"
+msgstr "Fila er ei mappe"
+
+#: ../daemon/gvfsbackendsftp.c:1809
+msgid "Failure"
+msgstr "Feil"
+
+#: ../daemon/gvfsbackendsftp.c:1874 ../daemon/gvfsbackendsftp.c:1936
+#: ../daemon/gvfsbackendsftp.c:1947 ../daemon/gvfsbackendsftp.c:2005
+#: ../daemon/gvfsbackendsftp.c:2095 ../daemon/gvfsbackendsftp.c:2124
+#: ../daemon/gvfsbackendsftp.c:2172 ../daemon/gvfsbackendsftp.c:2251
+#: ../daemon/gvfsbackendsftp.c:2362 ../daemon/gvfsbackendsftp.c:2403
+#: ../daemon/gvfsbackendsftp.c:2455 ../daemon/gvfsbackendsftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:2546 ../daemon/gvfsbackendsftp.c:2700
+#: ../daemon/gvfsbackendsftp.c:2726 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2842 ../daemon/gvfsbackendsftp.c:3122
+#: ../daemon/gvfsbackendsftp.c:3251 ../daemon/gvfsbackendsftp.c:3284
+#: ../daemon/gvfsbackendsftp.c:3386 ../daemon/gvfsbackendsftp.c:3427
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3519
+#: ../daemon/gvfsbackendsftp.c:3553 ../daemon/gvfsbackendsftp.c:3568
+#: ../daemon/gvfsbackendsftp.c:3587 ../daemon/gvfsbackendsftp.c:3665
+msgid "Invalid reply received"
+msgstr "Ugyldig svar motteken"
+
+#: ../daemon/gvfsbackendsftp.c:2193
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Feil under oppretting av sikkerhetskopi: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2608
+msgid "Unable to create temporary file"
+msgstr "Kan ikkje oppretta mellombels fil"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:214
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Passord kreves for delt ressurs %s på %s"
+
+#: ../daemon/gvfsbackendsmb.c:466 ../daemon/gvfsbackendsmb.c:506
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Intern feil (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:561
+msgid "Failed to mount Windows share"
+msgstr "Klarte ikkje å montere Windows-ressurs"
+
+#: ../daemon/gvfsbackendsmb.c:686 ../daemon/gvfsbackendsmb.c:1117
+msgid "Unsupported seek type"
+msgstr "Søkjetype ikkje støtta"
+
+#: ../daemon/gvfsbackendsmb.c:1171
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Oppretting av sikkerhetskopi mislukkast: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1602
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Feil under sletting av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1666
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Feil under flytting av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1690
+msgid "Can't move directory over directory"
+msgstr "Kan ikkje flytta mappe over mappe"
+
+#: ../daemon/gvfsbackendsmb.c:1738
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Feil under fjerning av målfil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1762
+msgid "Can't recursively move directory"
+msgstr "Kan ikkje flytta mappe rekursivt"
+
+#: ../daemon/gvfsbackendsmb.c:1825
+msgid "Windows Shares Filesystem Service"
+msgstr "Filsystemteneste for delte Windows-ressurser"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:702
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Delt Windows-ressurs på %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:794 ../daemon/gvfsbackendsmbbrowse.c:840
+msgid "The file is not a mountable"
+msgstr "Fila er ikkje monterbar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:862
+msgid "Not a regular file"
+msgstr "Ikkje ein vanleg fil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1107
+msgid "Not a directory"
+msgstr "Ikkje ei mappe"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1219
+msgid "Windows Network Filesystem Service"
+msgstr "Filsystemteneste for Windows nettverk"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:601 ../daemon/gvfsbackendtrash.c:1191
+msgid "Trash"
+msgstr "Papirkurv"
+
+#: ../daemon/gvfsbackendtrash.c:973
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (i papirkurv)"
+
+#: ../daemon/gvfsbackendtrash.c:1292
+msgid "Can't delete trash"
+msgstr "Kan ikkje slette søppel"
+
+#: ../daemon/gvfsbackendtrash.c:1639 ../daemon/gvfsbackendtrash.c:1714
+msgid "Trash directory notification not supported"
+msgstr "Varsling i papirkurv er ikkje støtta"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ugyldige type-motor"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Feil ved sending av fd: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:119
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:169 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operasjonen ikkje tillatt av motoren"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symbolske lenkjer er ikkje støtta av motoren"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "Ugyldig dbus-melding"
+
+#: ../daemon/main.c:47
+msgid "Replace old daemon."
+msgstr "Byt ut køyrande teneste."
+
+#: ../daemon/main.c:48
+msgid "Don't start fuse."
+msgstr "Ikkje start fuse."
+
+#: ../daemon/main.c:60
+msgid "GVFS Daemon"
+msgstr "GVFS-teneste"
+
+#: ../daemon/main.c:63
+msgid "Main daemon for GVFS"
+msgstr "Hovudteneste for GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:74
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:76 ../programs/gvfs-cat.c:165 ../programs/gvfs-cat.c:178
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:388 ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:133 ../programs/gvfs-open.c:146
+#: ../programs/gvfs-save.c:165 ../programs/gvfs-tree.c:253
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Prøv «%s --help» for meir informasjon."
+
+#: ../daemon/mount.c:432
+msgid "Invalid arguments from spawned child"
+msgstr "Ugyldige argumenter frå starta underprosess"
+
+#: ../daemon/mount.c:731
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatisk montering mislukkast: %s"
+
+#: ../daemon/mount.c:776
+msgid "The specified location is not mounted"
+msgstr "Spesifisert stad er ikkje montert"
+
+#: ../daemon/mount.c:781
+msgid "The specified location is not supported"
+msgstr "Spesifisert stad er ikkje støtta"
+
+#: ../daemon/mount.c:944
+msgid "Location is already mounted"
+msgstr "Lokasjonen er allereie montert"
+
+#: ../daemon/mount.c:952
+msgid "Location is not mountable"
+msgstr "Lokasjonen kan ikkje monterast"
+
+#: ../hal/ghaldrive.c:144
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../hal/ghaldrive.c:146
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../hal/ghaldrive.c:148
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../hal/ghaldrive.c:152
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../hal/ghaldrive.c:154
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../hal/ghaldrive.c:156
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../hal/ghaldrive.c:158
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../hal/ghaldrive.c:160
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../hal/ghaldrive.c:162
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../hal/ghaldrive.c:165
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../hal/ghaldrive.c:168
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../hal/ghaldrive.c:170
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../hal/ghaldrive.c:172
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../hal/ghaldrive.c:174
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../hal/ghaldrive.c:176
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../hal/ghaldrive.c:178
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../hal/ghaldrive.c:180
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../hal/ghaldrive.c:186
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-stasjon"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../hal/ghaldrive.c:192
+#, c-format
+msgid "%s Drive"
+msgstr "%s-stasjon"
+
+#: ../hal/ghaldrive.c:196
+msgid "Floppy Drive"
+msgstr "Diskettstasjon"
+
+#: ../hal/ghaldrive.c:202
+msgid "Software RAID Drive"
+msgstr "Stasjon med programvare-RAID"
+
+#: ../hal/ghaldrive.c:204
+msgid "USB Drive"
+msgstr "USB-disk"
+
+#: ../hal/ghaldrive.c:206
+msgid "ATA Drive"
+msgstr "ATA-stasjon"
+
+#: ../hal/ghaldrive.c:208
+msgid "SCSI Drive"
+msgstr "SCSI-stasjon"
+
+#: ../hal/ghaldrive.c:210
+msgid "FireWire Drive"
+msgstr "Firewire-stasjon"
+
+#: ../hal/ghaldrive.c:214
+msgid "Tape Drive"
+msgstr "Tape-stasjon"
+
+#: ../hal/ghaldrive.c:216
+msgid "CompactFlash Drive"
+msgstr "Compact Flash-stasjon"
+
+#: ../hal/ghaldrive.c:218
+msgid "MemoryStick Drive"
+msgstr "Minnepinne"
+
+#: ../hal/ghaldrive.c:220
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-stasjon"
+
+#: ../hal/ghaldrive.c:222
+msgid "SD/MMC Drive"
+msgstr "SD/MMC"
+
+#: ../hal/ghaldrive.c:224
+msgid "Zip Drive"
+msgstr "Zip-stasjon"
+
+#: ../hal/ghaldrive.c:226
+msgid "Jaz Drive"
+msgstr "Jaz-stasjon"
+
+#: ../hal/ghaldrive.c:228
+msgid "Thumb Drive"
+msgstr "Tommelstasjon"
+
+#: ../hal/ghaldrive.c:231
+msgid "Mass Storage Drive"
+msgstr "Masselagringseining"
+
+#: ../hal/ghaldrive.c:730
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Klarte ikkje å lause ut medie. Eitt eller fleire volum på mediet er opptatt."
+
+#: ../hal/ghalmount.c:166 ../hal/ghalvolume.c:155
+msgid "CD-ROM Disc"
+msgstr "CD-ROM-plate"
+
+#: ../hal/ghalmount.c:166 ../hal/ghalvolume.c:155
+msgid "Blank CD-ROM Disc"
+msgstr "Tom CD-ROM plate"
+
+#: ../hal/ghalmount.c:167 ../hal/ghalvolume.c:156
+msgid "CD-R Disc"
+msgstr "CD-R plate"
+
+#: ../hal/ghalmount.c:167 ../hal/ghalvolume.c:156
+msgid "Blank CD-R Disc"
+msgstr "Tom CD-R plate"
+
+#: ../hal/ghalmount.c:168 ../hal/ghalvolume.c:157
+msgid "CD-RW Disc"
+msgstr "CD-RW plate"
+
+#: ../hal/ghalmount.c:168 ../hal/ghalvolume.c:157
+msgid "Blank CD-RW Disc"
+msgstr "Tom CD-RW plate"
+
+#: ../hal/ghalmount.c:169 ../hal/ghalmount.c:171 ../hal/ghalvolume.c:158
+#: ../hal/ghalvolume.c:160
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM plate"
+
+#: ../hal/ghalmount.c:169 ../hal/ghalmount.c:171 ../hal/ghalvolume.c:158
+#: ../hal/ghalvolume.c:160
+msgid "Blank DVD-ROM Disc"
+msgstr "Tom DVD-ROM plate"
+
+#: ../hal/ghalmount.c:170 ../hal/ghalvolume.c:159
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM plate"
+
+#: ../hal/ghalmount.c:170 ../hal/ghalvolume.c:159
+msgid "Blank DVD-RAM Disc"
+msgstr "Tom DVD-RAM plate"
+
+#: ../hal/ghalmount.c:172 ../hal/ghalvolume.c:161
+msgid "DVD-RW Disc"
+msgstr "DVD-RW plate"
+
+#: ../hal/ghalmount.c:172 ../hal/ghalvolume.c:161
+msgid "Blank DVD-RW Disc"
+msgstr "Tom DVD-RW plate"
+
+#: ../hal/ghalmount.c:173 ../hal/ghalvolume.c:162
+msgid "DVD+R Disc"
+msgstr "DVD+R plate"
+
+#: ../hal/ghalmount.c:173 ../hal/ghalvolume.c:162
+msgid "Blank DVD+R Disc"
+msgstr "Tom DVD+R plate"
+
+#: ../hal/ghalmount.c:174 ../hal/ghalvolume.c:163
+msgid "DVD+RW Disc"
+msgstr "DVD+RW plate"
+
+#: ../hal/ghalmount.c:174 ../hal/ghalvolume.c:163
+msgid "Blank DVD+RW Disc"
+msgstr "Tom DVD+RW plate"
+
+#: ../hal/ghalmount.c:175 ../hal/ghalvolume.c:164
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL plate"
+
+#: ../hal/ghalmount.c:175 ../hal/ghalvolume.c:164
+msgid "Blank DVD+R DL Disc"
+msgstr "Tom DVD+R DL plate"
+
+#: ../hal/ghalmount.c:176 ../hal/ghalvolume.c:165
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray plate"
+
+#: ../hal/ghalmount.c:176 ../hal/ghalvolume.c:165
+msgid "Blank Blu-Ray Disc"
+msgstr "Tom Blu-Ray plate"
+
+#: ../hal/ghalmount.c:177 ../hal/ghalvolume.c:166
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R plate"
+
+#: ../hal/ghalmount.c:177 ../hal/ghalvolume.c:166
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tom Blu-Ray R plate"
+
+#: ../hal/ghalmount.c:178 ../hal/ghalvolume.c:167
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW plate"
+
+#: ../hal/ghalmount.c:178 ../hal/ghalvolume.c:167
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tom Blu-Ray RW plate"
+
+#: ../hal/ghalmount.c:179 ../hal/ghalvolume.c:168
+msgid "HD DVD Disc"
+msgstr "HD DVD plate"
+
+#: ../hal/ghalmount.c:179 ../hal/ghalvolume.c:168
+msgid "Blank HD DVD Disc"
+msgstr "Tom HD-DVD plate"
+
+#: ../hal/ghalmount.c:180 ../hal/ghalvolume.c:169
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R plate"
+
+#: ../hal/ghalmount.c:180 ../hal/ghalvolume.c:169
+msgid "Blank HD DVD-R Disc"
+msgstr "Tom HD DVD-R plate"
+
+#: ../hal/ghalmount.c:181 ../hal/ghalvolume.c:170
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW plate"
+
+#: ../hal/ghalmount.c:181 ../hal/ghalvolume.c:170
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tom HD DVD-RW plate"
+
+#: ../hal/ghalmount.c:182 ../hal/ghalvolume.c:171
+msgid "MO Disc"
+msgstr "MO-plate"
+
+#: ../hal/ghalmount.c:182 ../hal/ghalvolume.c:171
+msgid "Blank MO Disc"
+msgstr "Tom MO plate"
+
+#: ../hal/ghalmount.c:183 ../hal/ghalvolume.c:172
+msgid "Disc"
+msgstr "Disk"
+
+#: ../hal/ghalmount.c:183 ../hal/ghalvolume.c:172
+msgid "Blank Disc"
+msgstr "Tom disk"
+
+#: ../hal/ghalmount.c:368
+#, c-format
+msgid "%.1f kB Media"
+msgstr "%.1f kB medie"
+
+#: ../hal/ghalmount.c:373
+#, c-format
+msgid "%.1f MB Media"
+msgstr "%.1f MB medie"
+
+#: ../hal/ghalmount.c:378
+#, c-format
+msgid "%.1f GB Media"
+msgstr "%.1f GB medie"
+
+#: ../hal/ghalmount.c:490 ../hal/ghalvolume.c:318
+msgid "Mixed Audio/Data Disc"
+msgstr "Blanda lyd- og dataplate"
+
+#: ../hal/ghalvolume.c:206
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../hal/ghalvolume.c:211
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../hal/ghalvolume.c:216
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:306
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s krypterte data"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:329
+#, c-format
+msgid "%s Media"
+msgstr "%s medie"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:59
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s feil ved opning av fil: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:82
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, feil ved skriving til stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:94
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: feil ved lesing: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:112
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: feil ved lukking: %s\n"
+
+#: ../programs/gvfs-cat.c:138
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOKASJON ... - slå saman LOKASJONER til standard utdata."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:143
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Slå saman filer ved lokasjonar og skriv ut til standard utdata. Fungerer som det vanlege cat-verktøyet, men brukar gvfs lokasjonar i staden for lokale filer. Du kan til dømes bruka smb://tenar/ressurs/fil.txt som ein stad som skal vert viste."
+
+#: ../programs/gvfs-cat.c:150
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Merk: berre send dette gjennom cat viss du treng formateringsalternativa som -n -T eller anna."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:176 ../programs/gvfs-open.c:144
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: manglar lokasjonar"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:58
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: feil under opning av stad: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:85
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: feil under start av program: %s\n"
+
+#: ../programs/gvfs-open.c:115
+msgid "FILES... - open FILES with registered application."
+msgstr "FILER ... - opna FILER med registrert program."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:119
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Opnar fila(e) med programmet som er registrert som forval for å handtere denne type fil."
diff --git a/trunk/po/or.po b/trunk/po/or.po
new file mode 100644
index 00000000..5fd444eb
--- /dev/null
+++ b/trunk/po/or.po
@@ -0,0 +1,1631 @@
+# translation of or.po to Oriya
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Manoj Kumar Giri <mgiri@redhat.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: or\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-03-05 18:35+0000\n"
+"PO-Revision-Date: 2009-03-09 18:18+0530\n"
+"Last-Translator: Manoj Kumar Giri <mgiri@redhat.com>\n"
+"Language-Team: Oriya <oriya-it@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n\n"
+"\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "ପ୍ରୟୋଗ ସମର୍ଥିତ ନୁହଁ, ଫାଇଲଗୁଡ଼ିକ ଭିନ୍ନ ସ୍ଥାପନାରେ ଅଛି"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_infoରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_infoରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "ଧାରା ଫାଇଲ ବର୍ଣ୍ଣନାକାରୀକୁ ପାଇଲା ନାହିଁ"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "ଖୋଲିବାରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "ଧାରା ଫାଇଲ ବର୍ଣ୍ଣନାକାରୀକୁ ପାଇଲା ନଥିଲା"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "ଡ଼ାକରାରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_infoରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "ବନ୍ଦକରିବା ସ୍ଥାପନ ଖୋଜିପାରିଲା ନାହିଁ"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ଅବୈଧ ଫାଇଲ ନାମ %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "get_filesystem_infoରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dirରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_fileରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:299
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "ପ୍ରୟୋଗକୁ ବାତିଲ କରାଯାଇଛି"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "ଧାରା ପ୍ରୋଟୋକଲରେ ତ୍ରୁଟି: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "ଧାରାର ସମାପ୍ତି"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "ଧାରାରେ ଦୁର୍ବଳତା ସମର୍ଥିତ ନୁହଁ"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "ସ୍ଥାପନା ସୂଚନା ପାଇବାରେ ତ୍ରୁଟି: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "ଡେମନ ସହିତ ସଂଯୋଗ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_readରୁ ଅବୈଧ ଫେରସ୍ତ ମୂଲ୍ୟ"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "ସକେଟ ନିର୍ମାଣ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "ସକେଟ ସହିତ ସଂଯୋଗ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "ଅବୈଧ ଫାଇଲ ସୂଚନା ସଜ୍ଜିକରଣ ଶୈଳୀ"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "ଅବୈଧ ଗୁଣଧର୍ମ ସୂଚନା ତାଲିକା ସୂଚୀ"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Avahiକୁ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi ସମାଧାନକର୍ତ୍ତା ନିର୍ମାଣ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" ସର୍ଭିସ \"%s\" କୁ ଡମେନ \"%s\"ରେ ସମାଧାନ କରିବାରେ ତ୍ରୁଟି"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" ସର୍ଭିସ \"%s\" କୁ ଡମେନ \"%s\"ରେ ସମାଧାନ କରିବାରେ ତ୍ରୁଟି। ଏକ ଅବା ଅନେକ "
+"TXT ବିବରଣୀଗୁଡ଼ିକ ଅନୁପସ୍ଥିତ। କି ଆବଶ୍ୟକ: \"%s\"।"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" ସର୍ଭିସ \"%s\"କୁ ଡମେନ \"%s\"ରେ ସମାଧାନ କରିବାରେ ସମୟ ସମାପ୍ତ ହୋଇଥିଲା"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "ତ୍ରୁଟିଯୁକ୍ତ dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon ସାଙ୍କେତିକରଣର ସଂସ୍କରଣ %d କୁ ନିୟନ୍ତ୍ରଣ କରିପାରିବେ ନାହିଁ"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon ପାଇଁ ତ୍ରୁଟିଯୁକ୍ତ ନିବେଶ ତଥ୍ୟ"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus ସହିତ ସଂଯୋଗ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ଫାଇଲତନ୍ତ୍ର ସର୍ଭିସ"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ତ୍ରୁଟି: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ବ୍ୟବହାର ବିଧି: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ବ୍ୟବହାର ବିଧି: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "କୌଣସି ସ୍ଥାପନା ପ୍ରକାର ଉଲ୍ଲେଖ କରାଯାଇନାହିଁ"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s ପାଇଁ ସ୍ଥାପନା ବିନ୍ଦୁ ପୂର୍ବରୁ ଚାଲୁଅଛି"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "ସ୍ଥାପନ ଡେମନ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1912
+#, c-format
+msgid "/ on %s"
+msgstr "%s ଉପରେ /"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "No hostname specified"
+msgstr "କୌଣସି ଆଧାର ନାମ ଉଲ୍ଲେଖ ହୋଇନାହିଁ"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "ଅବୈଧ ସ୍ଥାପନା spec"
+
+#: ../daemon/gvfsbackendarchive.c:639 ../daemon/gvfsbackendarchive.c:689
+#: ../daemon/gvfsbackendarchive.c:718 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2264 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ଫାଇଲ ଅବସ୍ଥିତ ନାହିଁ"
+
+#: ../daemon/gvfsbackendarchive.c:727 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "ଫାଇଲଟି ଗୋଟିଏ ଡିରେକ୍ଟୋରୀ ନୁହଁ"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "ଲେଖନ୍ତୁ"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "ଅସ୍ଥାୟୀ ଡିରେକ୍ଟୋରୀ ନିର୍ମାଣ କରିବାରେ ଅସମର୍ଥ"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendburn.c:975
+#: ../daemon/gvfsbackendburn.c:1011 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "ଏପରି କୌଣସି ଫାଇ କିମ୍ବା ଡିରେକ୍ଟୋରୀ ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "ଡିରେକ୍ଟୋରୀ ଖାଲି ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:907
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ଉପରେ ଫାଇଲକୁ ନକଲ କରିପାରିବେ ନାହିଁ"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD ନିର୍ମାତା"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:927 ../daemon/gvfsbackendburn.c:989
+#: ../daemon/gvfsbackendburn.c:993 ../daemon/gvfsbackendburn.c:1003
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "ଫାଇଲ ଅବସ୍ଥିତ"
+
+#: ../daemon/gvfsbackendburn.c:830 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "ପୃଷ୍ଠଭୂମି ଦ୍ୱାରା ପ୍ରୟୋଗ ସମର୍ଥିତ ନୁହଁ"
+
+#: ../daemon/gvfsbackendburn.c:855
+msgid "No such file or directory in target path"
+msgstr "ଲକ୍ଷ୍ଯ ପଥରେ ଏପରି କୌଣସି ଫାଇଲ କିମ୍ବା ଡିରେକ୍ଟୋରୀ ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:878 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ଉପରେ ଡିରେକ୍ଟୋରୀ ନକଲ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:887 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "ଲକ୍ଷ୍ୟ ଫାଇଲ ଅବସ୍ଥିତ ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:894 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "ଡିରେକ୍ଟୋରୀକୁ ପୁନରାବର୍ତ୍ତି ଭାବରେ ନକଲ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendburn.c:953 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "ସମର୍ଥିତ ନୁହଁ"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "ତନ୍ତ୍ର ବସ ସହିତ ସଂଯୋଗ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "libhal ପ୍ରସଙ୍ଗ ନିର୍ମାଣ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "libhal କୁ ଆରମ୍ଭ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "କୌଣସି ଡ୍ରାଇଭ ଉଲ୍ଲେଖ ହୋଇନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ଡ୍ରାଇଭ %sକୁ ଖୋଜିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ଡ୍ରାଇଭ %s ଧ୍ୱନୀ ଫାଇଲଗୁଡ଼ିକୁ ଧାରଣ କରିପାରିବେ ନାହିଁ"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s ଉପରେ cdda ସ୍ଥାପନା"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325 ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "ଧ୍ୱନୀ ଡିସ୍କ"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ଫାଇଲ ତନ୍ତ୍ର ବ୍ୟସ୍ତ ଅଛି: %d ଖୋଲା ଫାଇଲ"
+msgstr[1] "ଫାଇଲ ତନ୍ତ୍ର ବ୍ୟସ୍ତ ଅଛି: %d ଖୋଲା ଫାଇଲଗୁଡ଼ିକ"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ଡ୍ରାଇଭ %s ଉପରେ ଏପରି କୌଣସି ଫାଇଲ %s ନାହିଁ"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ଡ୍ରାଇଭ %s ଉପରେ 'paranoia'ରୁ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ଡ୍ରାଇଭ %sରେ ଧାରା ଆଣିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "ଏପରି କୌଣସି ଫାଇଲ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ଫାଇଲ ଅବସ୍ଥିତ ନାହିଁ କିମ୍ବା ଏହା ଗୋଟିଏ ଧ୍ୱନି ଟ୍ରାକ"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "ଧ୍ୱନି CD ଫାଇଲ ତନ୍ତ୍ର ସର୍ଭିସ"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "କମ୍ପୁଟର"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ଫାଇଲ ତନ୍ତ୍ର"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:691
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ଖୋଲି ପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "ସ୍ଥାପନଯୋଗ୍ୟ ଫାଇଲ ଖୋଲି ପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1055
+#, c-format
+msgid "Internal error: %s"
+msgstr "ଆଭ୍ୟନ୍ତରୀଣ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ଫାଇଲ ସ୍ତାପନ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ଡ୍ରାଇଭରେ କୌଣସି ଫାଇଲ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "ଗୋଟିଏ ସ୍ଥାପନଯୋଗ୍ୟ ଫାଇଲ ନୁହଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ଫାଇଲକୁ ବିସ୍ଥାପନ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ଫାଇଲକୁ ବାହାର କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "ଉତ୍ତର ବିଶ୍ଳେଷଣ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "ଖାଲି ଉତ୍ତର"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "ସର୍ଭରରୁ ଅପ୍ରତ୍ୟାଶିତ ଉତ୍ତର"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "ଅବୈଧ ଉତ୍ତର"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV ସହଭାଗ"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "ଦୟାକରି ପ୍ରକ୍ସି ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV ସକ୍ରିୟ ସହଭାଗ ନୁହଁ"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s ଉପରେ WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "ଅନୁରୋଧ ନିର୍ମାଣ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528 ../daemon/gvfsbackendsftp.c:3783
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "ଲକ୍ଷ୍ଯ ଫାଇଲ ପୂର୍ବରୁ ଅବସ୍ଥିତ ଅଛି"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2950
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "ଫାଇଲଟି ବାହାରୁ ପରିବର୍ତ୍ତନ କରାଯାଇଥିଲା"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "ନକଲ ସଂରକ୍ଷଣ ଫାଇଲ ନିର୍ମାଣ କରିବାରେ ବିଫଳ"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "ସ୍ଥାନିୟ ନେଟୱର୍କ"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ଫାଇଲ କିମ୍ବା ଡିରେକ୍ଟୋରୀକୁ ନିରିକ୍ଷଣ କରିପାରିବେ ନାହିଁ।"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "ନେଟୱର୍କ"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "ଖାତାଗୁଡ଼ିକ ସମର୍ଥିତ ନୁହଁ"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "ଆଧାର ବନ୍ଦ ସଂଯୋଗ"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "ତଥ୍ୟ ସଂଯୋଗକୁ ଖୋଲିହେବ ନାହିଁ। ହୁଏତଃ ଆପଣଙ୍କର ଅଗ୍ନି କବଚ ଏହାକୁ ପ୍ରତିରୋଧ କରୁଥାଇପାରେ?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "ତଥ୍ୟ ସଂଯୋଗ ବନ୍ଦ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "ପ୍ରୟୋଗ ବିଫଳ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "ସର୍ଭରରେ କୌଣସି ସ୍ଥାନ ବଳିନାହିଁ"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4094
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "ପ୍ରୟୋଗ ସମର୍ଥିତ ନୁହଁ"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "ଅନୁମତି ପ୍ରତ୍ୟାଖାନ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "ପୃଷ୍ଠା ପ୍ରକାର ଅଜଣା"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "ଅବୈଧ ଫାଇଲ ନାମ"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "ଅବୈଧ ଉତ୍ତର"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "ଭଙ୍ଗା ପରିବହନ"
+
+#: ../daemon/gvfsbackendftp.c:713 ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "ଆଧାର ସହିତ ସଂଯୋଗ ହୋଇପାରିଲା ନାହିଁ"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "%s ପରି %s ଉପରେ ftp ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s ଉପରେ ftp ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendftp.c:1525 ../daemon/gvfsbackendsftp.c:877
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "ପ୍ରବେଶ ସଂକେତ ସଂଳାପ ବାତିଲ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "%s ଉପରେ ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s ପରି %s ଉପରେ ftp"
+
+#: ../daemon/gvfsbackendftp.c:1692 ../daemon/gvfsbackendsftp.c:1976
+#: ../daemon/gvfsbackendsftp.c:3774
+msgid "File is directory"
+msgstr "ଫାଇଲଟି ଡିରେକ୍ଟୋରୀ ଅଟେ"
+
+#: ../daemon/gvfsbackendftp.c:1914 ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2811
+msgid "backups not supported yet"
+msgstr "ନକଲ ସଂରକ୍ଷଣ ଏପର୍ଯ୍ୟନ୍ତ ସମର୍ଥିତ ହୋଇନାହିଁ"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "ଫାଇଲ ନାମ ବହୁତ ବଡ଼"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "ଅବୈଧ ଲକ୍ଷ୍ଯସ୍ଥଳ ଫାଇଲନାମ"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: ଡିରେକ୍ଟୋରୀ କିମ୍ବା ଫାଇଲ ଅବସ୍ଥିତ"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: ଏପରି କୌଣସି ଫାଇଲ କିମ୍ବା ଡିରେକ୍ଟୋରୀ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ଅବୈଧ ଫାଇଲ ନାମ"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ସମର୍ଥିତ ନୁହଁ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ଡିଜିଟାଲ କ୍ୟାମେରା (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s କ୍ୟାମେରା"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ଧ୍ୱନି ଚାଳକ"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "କ୍ୟାମେରା"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "ଧ୍ୱନି ଚାଳକ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "କୌଣସି ଉପକରଣ ଉଲ୍ଲେଖ ହୋଇନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 ପ୍ରସଙ୍ଗ ନିର୍ମାଣ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "କ୍ୟାମେରା ନିର୍ମାଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "ଉପକରଣ ସୂଚନା ଧାରଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "ଉପକରଣ ସୂଚନା ଅବଲୋକନ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "ଉପକରଣ ସୂଚନା ପାଇବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "କ୍ୟାମେରା ସଞ୍ଚାର ସଂଯୋଗିକୀକୁ ବିନ୍ୟାସ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "କ୍ୟାମେରା ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s ଉପରେ gphoto2 ସ୍ଥାପିତ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "କୌଣସି କ୍ୟାମେରା ଉଲ୍ଲେଖ ହୋଇନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "ଫାଇଲ ବସ୍ତୁ ନିର୍ମାଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "ଫାଇଲ ପାଇବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "ଫାଇଲରୁ ତଥ୍ୟ ପାଇବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "ତ୍ରୁଟିଯୁକ୍ତ ଚିତ୍ରସଂକେତ ପରିଚାୟକ '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "କ୍ୟାମେରା %sରେ ଧାରା ଆଣିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "ଗୋଟିଏ ଡିରେକ୍ଟୋରୀ ନୁହଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "ଫୋଲଡର ତାଲିକା ପାଇବାରେ ବିଫଳ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "ଫାଇଲ ତାଲିକା ପାଇବାରେ ବିଫଳ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ନିର୍ମାଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "ନାମ ପୂର୍ବରୁ ଅବସ୍ଥିତ ଅଛି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "ନୂତନ ନାମଟି ବହୁତ ବଡ଼"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "ଡ଼ିରେକ୍ଟୋରୀକୁ ପୁନଃ ନାମକରଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "ଫାଇଲକୁ ପୁନଃ ନାମକରଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "ଡିରେକ୍ଟୋରୀ '%s' ଟି ଖାଲି ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ଅପସାରଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "ଫାଇଲ ଅପସାରଣ କରିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "ଡିରେକ୍ଟୋରୀରେ ଲେଖିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "ଯୋଡିବା ପାଇଁ ନୂତନ ଫାଇଲ ବଣ୍ଟନ କରିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "ଯୋଡିବା ପାଇଁ ଫାଇଲ ପଢ଼ିପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "ଯୋଡିବା ପାଇଁ ଫାଇଲର ତଥ୍ୟ ପାଇ ପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "ଫାଇଲ ଲେଖିବାରେ ତ୍ରୁଟି"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "ସମର୍ଥିତ ନୁହଁ (ସମାନ ଡିରେକ୍ଟୋରୀ ନୁହଁ)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "ସମର୍ଥିତ ନୁହଁ (src ଟି dir, dst ଟି dir)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "ସମର୍ଥିତ ନୁହଁ (src ଟି dir, dst ଟି ସ୍ଥିତବାନ ଫାଇଲ)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "ସମର୍ଥିତ ନୁହଁ (src ଟି ଫାଇଲ ଅଟେ, dst ଟି dir)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP କ୍ଲାଏଣ୍ଟ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1900
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ଅବୈଧ ସାଙ୍କେତିକରଣ)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ଡିରେକ୍ଟୋରୀ ବିଜ୍ଞପ୍ତି ସମର୍ଥିତ ନୁହଁ"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "ୱିଣ୍ଡୋ ନେଟୱର୍କ"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "ନେଟୱର୍କ ସ୍ଥିତି ନିରିକ୍ଷକ"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s ଉପରେ %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB ସମର୍ଥନ ଅନୁପସ୍ଥିତ। ଦୟାକରି ଆପଣଙ୍କର ସଫ୍ଟୱେର ବିକ୍ରେତାଙ୍କ ସହିତ ଯୋଗାଯୋଗ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "ଉପକରଣକୁ ସଂଯୋଗ ବିଚ୍ଛିନ୍ନ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "ଉପକରଣଟି ଗୋଟିଏ ସଫ୍ଟୱେର ଅଦ୍ୟତନ ଆବଶ୍ୟକ କରୁଅଛି"
+
+#: ../daemon/gvfsbackendsftp.c:291
+msgid "ssh program unexpectedly exited"
+msgstr "ssh ପ୍ରଗ୍ରାମଟି ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ଉତ୍ତେଜିତ ହେଲା"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "ଆଧାର ନାମ ଜଣାନାହିଁ"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "ଆଧାର ପାଇଁ କୌଣସି ରାସ୍ତା ନାହିଁ"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "ସର୍ଭର ଦ୍ୱାରା ସଂଯୋଗ ବାରଣ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "ଆଧାର କି ଯାଞ୍ଚ ବିଫଳ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "ssh ପ୍ରଗ୍ରାମକୁ କାର୍ଯ୍ୟକାରୀ କରିବାରେ ଅସମର୍ଥ"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh ପ୍ରଗ୍ରାମକୁ କାର୍ଯ୍ୟକାରୀ କରିବାରେ ଅସମର୍ଥ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:783
+msgid "Timed out when logging in"
+msgstr "ଲଗଇନ ହେବା ସମୟରେ ସମୟ ସମାପ୍ତ ହୋଇଥିଲା"
+
+#: ../daemon/gvfsbackendsftp.c:861
+msgid "Enter passphrase for key"
+msgstr "କି ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendsftp.c:863
+msgid "Enter password"
+msgstr "ପ୍ରବେଶ ସଂକେତ ଭରଣ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send password"
+msgstr "ପ୍ରବେଶ ସଂକେତ ପଠାଇ ପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Log In Anyway"
+msgstr "ଯେକୌଣସି ପ୍ରକାରେ ଲଗଇନ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendsftp.c:947
+msgid "Cancel Login"
+msgstr "ଲଗଇନ ବାତିଲ କରନ୍ତୁ"
+
+#: ../daemon/gvfsbackendsftp.c:957
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:977
+msgid "Login dialog cancelled"
+msgstr "ଲଗଇନ ସଂଳାପ ବାତିଲ ହୋଇଛି"
+
+#: ../daemon/gvfsbackendsftp.c:997
+msgid "Can't send host identity confirmation"
+msgstr "ଆଧାର ପରିଚୟ ନିଶ୍ଚିତତା ପଠାଇପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendsftp.c:1490 ../daemon/gvfsbackendsftp.c:1513
+msgid "Protocol error"
+msgstr "ପ୍ରୋଟୋକଲ ତ୍ରୁଟି"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1538
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "%s ପାଇଁ %s ଉପରେ sftp"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1541
+#, c-format
+msgid "sftp on %s"
+msgstr "%s ଉପରେ sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1567
+msgid "Unable to find supported ssh command"
+msgstr "ସମର୍ଥିତ ssh ନିର୍ଦ୍ଦେଶ ଖୋଜିବାରେ ଅସମର୍ଥ"
+
+#: ../daemon/gvfsbackendsftp.c:1985
+msgid "Failure"
+msgstr "ବିଫଳତା"
+
+#: ../daemon/gvfsbackendsftp.c:2041 ../daemon/gvfsbackendsftp.c:2120
+#: ../daemon/gvfsbackendsftp.c:2131 ../daemon/gvfsbackendsftp.c:2187
+#: ../daemon/gvfsbackendsftp.c:2273 ../daemon/gvfsbackendsftp.c:2323
+#: ../daemon/gvfsbackendsftp.c:2369 ../daemon/gvfsbackendsftp.c:2444
+#: ../daemon/gvfsbackendsftp.c:2551 ../daemon/gvfsbackendsftp.c:2591
+#: ../daemon/gvfsbackendsftp.c:2641 ../daemon/gvfsbackendsftp.c:2713
+#: ../daemon/gvfsbackendsftp.c:2725 ../daemon/gvfsbackendsftp.c:2783
+#: ../daemon/gvfsbackendsftp.c:2825 ../daemon/gvfsbackendsftp.c:3002
+#: ../daemon/gvfsbackendsftp.c:3027 ../daemon/gvfsbackendsftp.c:3082
+#: ../daemon/gvfsbackendsftp.c:3139 ../daemon/gvfsbackendsftp.c:3410
+#: ../daemon/gvfsbackendsftp.c:3477 ../daemon/gvfsbackendsftp.c:3612
+#: ../daemon/gvfsbackendsftp.c:3672 ../daemon/gvfsbackendsftp.c:3707
+#: ../daemon/gvfsbackendsftp.c:3735 ../daemon/gvfsbackendsftp.c:3843
+#: ../daemon/gvfsbackendsftp.c:3897 ../daemon/gvfsbackendsftp.c:3933
+#: ../daemon/gvfsbackendsftp.c:3967 ../daemon/gvfsbackendsftp.c:3982
+#: ../daemon/gvfsbackendsftp.c:3997 ../daemon/gvfsbackendsftp.c:4075
+msgid "Invalid reply received"
+msgstr "ଅବୈଧ ଉତ୍ତର ଗ୍ରହଣ କରାଯାଇଛି"
+
+#: ../daemon/gvfsbackendsftp.c:2093
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForReadରେ ଅବୈଧ icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2389
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "ନକଲ ସଂରକ୍ଷଣ ଫାଇଲ ସୃଷ୍ଟିକରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2887
+msgid "Unable to create temporary file"
+msgstr "ଅସ୍ଥାୟୀ ଫାଇଲ ନିର୍ମାଣ କରିବାରେ ଅସମର୍ଥ"
+
+#: ../daemon/gvfsbackendsftp.c:3769 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "ଡିରେକ୍ଟୋରୀ ଉପରେ ଡିରେକ୍ଟୋରୀ ଚଲାଇପାରିବେ ନାହିଁ"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%s ଉପରେ %s ସହଭାଗ କରିବା ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଆବଶ୍ୟକ"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "ଆଭ୍ୟନ୍ତରୀଣ ତ୍ରୁଟି (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Windows ସହଭାଗକୁ ସ୍ଥାପନ କରିବାରେ ବିଫଳ"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "ଅସମର୍ଥିତ seek ପ୍ରକାର"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "ନକଲସଂରକ୍ଷଣ ଫାଇଲ ସୃଷ୍ଟି କରିବାରେ ବିଫଳ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ଫାଇଲ ଅପସାରଣ କରିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ଫାଇଲ ଘୁଞ୍ଚାଇବାରେ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "ଲକ୍ଷ୍ୟ ଫାଇଲ କାଢ଼ିବାରେ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "ଡିରେକ୍ଟୋରୀକୁ ପୁନରାବର୍ତ୍ତି ଭାବରେ ଘୁଞ୍ଚାଇପାରିବେ ନାହିଁ"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows ସହଭାଗୀ ଫାଇଲତନ୍ତ୍ର ସର୍ଭିସ"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s ପାଇଁ ପ୍ରବେଶ ସଂକେତ ଆବଶ୍ୟକ"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s ଉପରେ Windows ସହଭାଗ"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "ସର୍ଭରରୁ ସହଭାଗ ତାଲିକା କାଢ଼ିବାରେ ବିଫଳ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "ଫାଇଲଟି ସ୍ଥାପନଯୋଗ୍ୟ ନୁହଁ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "ଗୋଟିଏ ନିୟମିତ ଫାଇଲ ନୁହଁ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows ନେଟୱର୍କ ଫାଇଲତନ୍ତ୍ର ସର୍ଭିସ"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "ଆବର୍ଜନା ପାତ୍ର ଫୋଲଡରକୁ ଅପସାରଣ କରାଯାଇନପାରେ"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "ଆବର୍ଜନା ପାତ୍ରରେ ଥିବା ବସ୍ତୁ ଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରାଯାଇନପାରେ"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "ଆବର୍ଜନା ପାତ୍ର"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "ଅବୈଧ ପୃଷ୍ଠଭୂମି ପ୍ରକାର"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd ପଠାଇବାରେ ତ୍ରୁଟି: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symlinks ପୃଷ୍ଠଭୂମି ଦ୍ୱାରା ସମର୍ଥିତ ନୁହଁ"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "ଅବୈଧ dbus ସନ୍ଦେଶ"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "ପୁରୁଣା ଡେମନକୁ ସ୍ଥାନାନ୍ତରିତ କରନ୍ତୁ।"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "ଫ୍ୟୁଜ ଆରମ୍ଭ କରନ୍ତୁ ନାହିଁ।"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS ଡେମନ"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS ପାଇଁ ମୂଖ୍ୟ ଡେମନ"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "ଅଧିକ ସୂଚନା ପାଇଁ \"%s --help\"କୁ ଚେଷ୍ଟାକରନ୍ତୁ।"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "spawned childରୁ ଅବୈଧ ସ୍ୱତନ୍ତ୍ରଚର"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "ସ୍ୱୟଂସ୍ଥାପନ ବିଫଳ ହୋଇଛି: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "ନିର୍ଦ୍ଧିଷ୍ଟିତ ସ୍ଥାନଟି ସ୍ଥାପିତ ନାହିଁ"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "ନିର୍ଦ୍ଧିଷ୍ଟିତ ସ୍ଥାନଟି ସମର୍ଥିତ ନାହିଁ"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "ସ୍ଥାନଟି ପୂର୍ବରୁ ସ୍ଥାପିତ"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "ସ୍ଥାନଟି ସ୍ଥାପନଯୋଗ୍ୟ ନୁହଁ"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ଖାଲି CD-ROM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ଖାଲି CD-R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ଖାଲି CD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ଖାଲି DVD-ROM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ଖାଲି DVD-RAM ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ଖାଲି DVD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ଖାଲି DVD+R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ଖାଲି DVD+RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ଖାଲି DVD+R DL ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ଖାଲି Blu-Ray ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ଖାଲି Blu-Ray R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ଖାଲି Blu-Ray RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ଖାଲି HD DVD ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ଖାଲି HD DVD-R ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ଖାଲି HD DVD-RW ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ଖାଲି MO ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "ଡିସ୍କ"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ଖାଲି ଡିସ୍କ"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ଡ୍ରାଇଭ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "%s ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "ଫ୍ଲପି ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "ସଫ୍ଟୱେର RAID ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "USB ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "ATA ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "SCSI ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "FireWire ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "ଟେପ ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "CompactFlash ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "MemoryStick ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "SmartMedia ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Zip ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Jaz ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "Thumb ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "ସମୂହ ଭଣ୍ଡାର ଡ୍ରାଇଭ"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "ମେଡିଆ ବାହାର କରିବାରେ ବିଫଳ; ମେଡିଆରେ ଥିବା ଗୋଟିଏ କିମ୍ବା ଅଧିକ ସ୍ଥାନ ବ୍ୟସ୍ତଅଛି।"
+
+#: ../monitor/hal/ghalmount.c:159 ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:164 ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:169 ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:323 ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "ମିଶ୍ରିତ ଧ୍ୱନି/ତଥ୍ୟ ଡିସ୍କ"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336 ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "%s ମେଡିଆ"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s ସଂଗୁପ୍ତ ତଥ୍ୟ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ଫାଇଲ ଖୋଲିବାରେ ତ୍ରୁଟି: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, ରେ ଲେଖିବାରେ ତ୍ରୁଟି"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: ପଢ଼ିବାରେ ତ୍ରୁଟି: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:ବନ୍ଦକରିବାରେ ତ୍ରୁଟି: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - LOCATIONS କୁ ମାନକ ଫଳାଫଳରେ ଯୋଡନ୍ତୁ।"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ଅନୁପସ୍ଥିତ ସ୍ଥାନ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: ସ୍ଥାନକୁ ଖୋଲିବାରେ ତ୍ରୁଟି: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: ପ୍ରୟୋଗ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - FILES କୁ ପଞ୍ଜିକୃତ ପ୍ରୟୋଗ ସହିତ ଖୋଲନ୍ତୁ।"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "ଫାଇଲର ପ୍ରକାର ନିୟନ୍ତ୍ରଣ କରିବା ପାଇଁ ପଞ୍ଜିକୃତ ପୂର୍ବନିର୍ଦ୍ଧାରିତ ଫାଇଲକୁ ଖୋଲନ୍ତୁ।"
+
diff --git a/trunk/po/pa.po b/trunk/po/pa.po
new file mode 100644
index 00000000..180f2984
--- /dev/null
+++ b/trunk/po/pa.po
@@ -0,0 +1,1350 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Amanpreet Singh Alam <apreet.alam@gmail.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-03 09:02+0000\n"
+"PO-Revision-Date: 2008-03-04 23:11+0530\n"
+"Last-Translator: Amanpreet Singh Alam <apreet.alam@gmail.com>\n"
+"Language-Team: Punjabi/Panjabi <punjabi-users@list.sf.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: LoKalize 0.2\n"
+
+#: ../client/gdaemonfile.c:464 ../client/gdaemonfile.c:1867
+msgid "Operation not supported, files on different mounts"
+msgstr "ਓਪਰੇਸ਼ਨ ਸਹਾਇਕ ਨਹੀਂ ਹੈ, ਫਾਇਲਾਂ ਵੱਖਰੇ ਮਾਊਂਟ ਉੱਤੇ ਹਨ"
+
+#: ../client/gdaemonfile.c:758
+msgid "Invalid return value from get_info"
+msgstr "get_info ਤੋਂ ਗਲਤ ਜਵਾਬ ਆਇਆ"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from query_info"
+msgstr "query_info ਤੋਂ ਗਲਤ ਜਵਾਬ ਆਇਆ"
+
+#: ../client/gdaemonfile.c:865
+msgid "Couldn't get stream file descriptor"
+msgstr "ਸਟਰੀਮ ਫਾਈਲ ਡਿਸਕ੍ਰਿਪਟਰ ਲਈ ਨਹੀਂ ਜਾ ਸਕੀ"
+
+#: ../client/gdaemonfile.c:897 ../client/gdaemonfile.c:967
+#: ../client/gdaemonfile.c:1026 ../client/gdaemonfile.c:1085
+#: ../client/gdaemonfile.c:1147
+msgid "Invalid return value from open"
+msgstr "ਖੋਲ੍ਹਣ ਤੋਂ ਗਲਤ ਮੁੱਲ ਮਿਲਿਆ"
+
+#: ../client/gdaemonfile.c:977 ../client/gdaemonfile.c:1036
+#: ../client/gdaemonfile.c:1095 ../client/gdaemonfile.c:1157
+msgid "Didn't get stream file descriptor"
+msgstr "ਸਟਰੀਮ ਫਾਈਲ ਡਿਸਕ੍ਰਿਪਟਰ ਲਈ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../client/gdaemonfile.c:1209 ../client/gdaemonfile.c:1226
+msgid "Invalid return value from call"
+msgstr "ਕਾਲ ਤੋਂ ਗਲਤ ਵਾਪਿਸ"
+
+#: ../client/gdaemonfile.c:1505
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info ਤੋਂ ਗਲਤ ਜਵਾਬ ਮੁੱਲ"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1549
+msgid "Could not find enclosing mount"
+msgstr "ਇਨਕਲੋਜ਼ਿੰਗ ਮਾਊਂਟ ਨਹੀਂ ਲੱਭਿਆ ਜਾ ਸਕਿਆ"
+
+#: ../client/gdaemonfile.c:1579
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ਗਲਤ ਫਾਇਲ ਨਾਂ %s"
+
+#: ../client/gdaemonfile.c:1621
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info ਤੋਂ ਗਲਤ ਜਵਾਬ ਮੁੱਲ"
+
+#: ../client/gdaemonfile.c:2012
+msgid "Invalid return value from monitor_dir"
+msgstr "ਮਾਨੀਟਰ ਡਾਇਰੈਕਟਰੀ ਤੋਂ ਗਲਤ ਜਵਾਬ(_d)"
+
+#: ../client/gdaemonfile.c:2061
+msgid "Invalid return value from monitor_file"
+msgstr "ਮਾਨੀਟਰ ਫਾਈਲ ਤੋਂ ਗਲਤ ਜਵਾਬ ਆਇਆ(_f)"
+
+#: ../client/gdaemonfileinputstream.c:451
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1304
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:403
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../client/gdaemonfileoutputstream.c:1062
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "ਸਟਰੀਮ ਪਰੋਟੋਕਾਲ ਵਿੱਚ ਗਲਤੀ: %s"
+
+#: ../client/gdaemonfileinputstream.c:459
+#: ../client/gdaemonfileinputstream.c:1314
+#: ../client/gdaemonfileoutputstream.c:411
+#: ../client/gdaemonfileoutputstream.c:1062
+msgid "End of stream"
+msgstr "ਸਟਰੀਮ ਖਤਮ ਹੋਈ"
+
+#: ../client/gdaemonfileinputstream.c:519
+#: ../client/gdaemonfileinputstream.c:676
+#: ../client/gdaemonfileinputstream.c:785
+#: ../client/gdaemonfileinputstream.c:1036
+#: ../client/gdaemonfileoutputstream.c:460
+#: ../client/gdaemonfileoutputstream.c:639
+#: ../client/gdaemonfileoutputstream.c:835 ../daemon/gvfsbackendftp.c:824
+#: ../daemon/gvfsbackendobexftp.c:753 ../daemon/gvfsbackendobexftp.c:774
+#: ../daemon/gvfsbackendobexftp.c:893 ../daemon/gvfsbackendobexftp.c:1030
+#: ../daemon/gvfsbackendobexftp.c:1093 ../daemon/gvfsbackendobexftp.c:1218
+#: ../daemon/gvfsbackendobexftp.c:1245 ../daemon/gvfsbackendobexftp.c:1304
+#: ../daemon/gvfsbackendobexftp.c:1326 ../daemon/gvfsbackendobexftp.c:1385
+#: ../daemon/gvfsbackendobexftp.c:1404 ../daemon/gvfsbackendsmb.c:1014
+#: ../daemon/gvfsbackendtest.c:87 ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183 ../daemon/gvfschannel.c:297
+msgid "Operation was cancelled"
+msgstr "ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ"
+
+#: ../client/gdaemonfileinputstream.c:1211
+#: ../client/gdaemonfileoutputstream.c:946
+msgid "Seek not supported on stream"
+msgstr "ਸਟਰੀਮ ਉੱਤੇ ਸਹਿਯੋਗ ਉਪਲੱਬਧ ਨਹੀਂ ਹੈ"
+
+#: ../client/gdaemonfileinputstream.c:1241
+msgid "The query info operation is not supported"
+msgstr "ਕਿਊਰੀ ਜਾਣਕਾਰੀ ਓਪਰੇਸ਼ਨ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#: ../client/gdaemonvfs.c:604
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "ਮਾਊਂਟ ਜਾਣਕਾਰੀ ਲੈਣ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../client/gvfsdaemondbus.c:559 ../client/gvfsdaemondbus.c:946
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "ਡੈਮਨ ਨਾਲ ਕੁਨੈਕਟ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../common/gsysutils.c:127
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "ਸਾਕਟ ਬਣਾਉਣ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../common/gsysutils.c:165
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "ਸਾਕਟ ਨਾਲ ਕੁਨੈਕਟ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "ਗਲਤ ਫਾਇਲ ਜਾਣਕਾਰੀ ਫਾਰਮੈਟ"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "ਗਲਤ ਗੁਣ ਜਾਣਕਾਰੀ ਲਿਸਟ ਸਮੱਗਰੀ"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "ਡੀ-ਬੱਸ ਨਾਲ ਕੁਨੈਕਟ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ਫਾਈਲ ਸਿਸਟਮ ਸਰਵਿਸ"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ਗਲਤੀ: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ਵਰਤੋਂ: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ਵਰਤੋਂ: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ਕੋਈ ਮਾਊਂਟ ਟਾਈਪ ਨਹੀਂ ਦਿੱਤੀ"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s ਲਈ ਮਾਊਂਟ-ਪੁਆਇੰਟ ਪਹਿਲਾਂ ਹੀ ਚੱਲ ਰਿਹਾ ਹੈ"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "ਮਾਊਂਟ ਡੈਮਨ ਸਟਾਰਟ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:347
+msgid "Burn"
+msgstr "ਲਿਖੋ"
+
+#: ../daemon/gvfsbackendburn.c:377
+msgid "Unable to create temporary directory"
+msgstr "ਆਰਜ਼ੀ ਡਾਇਰੈਕਟਰੀ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ"
+
+#: ../daemon/gvfsbackendburn.c:406 ../daemon/gvfsbackendburn.c:417
+#: ../daemon/gvfsbackendburn.c:452 ../daemon/gvfsbackendburn.c:673
+#: ../daemon/gvfsbackendburn.c:720 ../daemon/gvfsbackendburn.c:746
+#: ../daemon/gvfsbackendburn.c:784
+msgid "No such file or directory"
+msgstr "ਕੋਈ ਇੰਝ ਦੀ ਫਾਇਲ ਜਾਂ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendburn.c:426 ../daemon/gvfsbackenddav.c:1757
+msgid "Directory not empty"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਖਾਲੀ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendburn.c:460 ../daemon/gvfsbackendburn.c:898
+msgid "Can't copy file over directory"
+msgstr "ਫਾਇਲ ਡਾਇਰੈਕਟਰੀ ਕਾਪੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:652
+msgid "CD/DVD Creator"
+msgstr "CD/DVD ਕਰੀਏਟਰ"
+
+#: ../daemon/gvfsbackendburn.c:681 ../daemon/gvfsbackendcomputer.c:652
+#: ../daemon/gvfsbackenddnssd.c:393 ../daemon/gvfsbackendftp.c:742
+#: ../daemon/gvfsbackendnetwork.c:637
+#, c-format
+msgid "The file is not a directory"
+msgstr "ਫਾਇਲ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendburn.c:756 ../daemon/gvfsbackendburn.c:792
+#: ../daemon/gvfsbackendburn.c:918
+msgid "File exists"
+msgstr "ਫਾਇਲ ਮੌਜੂਦ ਹੈ"
+
+#: ../daemon/gvfsbackendburn.c:846
+msgid "No such file or directory in target path"
+msgstr "ਟਾਰਗੇਟ ਪਾਥ ਵਿੱਚ ਫਾਇਲ ਜਾਂ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendburn.c:869
+msgid "Can't copy directory over directory"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਡਾਇਰੈਕਟਰੀ ਉੱਤੇ ਕਾਪੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendburn.c:878
+msgid "Target file exists"
+msgstr "ਟਾਰਗੇਟ ਫਾਇਲ ਮੌਜੂਦ ਹੈ"
+
+#: ../daemon/gvfsbackendburn.c:885
+msgid "Can't recursively copy directory"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਲਗਾਤਾਰ ਕਾਪੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendburn.c:944
+msgid "Not supported"
+msgstr "ਸਹਾਇਕ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendcdda.c:264 ../daemon/gvfsbackendcdda.c:335
+msgid "No drive specified"
+msgstr "ਡਰਾਈਵ ਨਹੀਂ ਦਿੱਤੀ ਹੈ"
+
+#: ../daemon/gvfsbackendcdda.c:279
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "ਡਰਾਈਵ %s ਨਹੀਂ ਲੱਭੀ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendcdda.c:289
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ਡਰਾਈਵ %s ਆਡੀਓ ਫਾਈਲਾਂ ਨਹੀਂ ਰੱਖਦੀ ਹੈ"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:297
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda %s ਉੱਤੇ ਮਾਊਂਟ ਹੈ"
+
+#: ../daemon/gvfsbackendcdda.c:298 ../daemon/gvfsbackendcdda.c:802
+#: ../hal/ghalmount.c:488 ../hal/ghalvolume.c:286 ../hal/ghalvolume.c:307
+#, c-format
+msgid "Audio Disc"
+msgstr "ਆਡੀਓ ਡਿਸਕ"
+
+#: ../daemon/gvfsbackendcdda.c:359
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ਫਾਇਲ ਸਿਸਟਮ ਬਿਜ਼ੀ ਹੈ: %d ਫਾਇਲ ਖੁੱਲ੍ਹੀ"
+msgstr[1] "ਫਾਇਲ ਸਿਸਟਮ ਬਿਜ਼ੀ ਹੈ: %d ਫਾਇਲਾਂ ਖੁੱਲ੍ਹੀਆਂ"
+
+#: ../daemon/gvfsbackendcdda.c:549
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ਡਰਾਈਵ %2$s ਉੱਤੇ ਫਾਈਲ %1$s ਨਹੀਂ ਹੈ"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:658
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "ਡਰਾਈਵ %s ਉੱਤੇ 'paranoia' ਤੋਂ ਗਲਤੀ"
+
+#: ../daemon/gvfsbackendcdda.c:721
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "ਡਰਾਈਵ %s ਤੋਂ ਸਟਰੀਮ ਲੈਣ ਦੌਰਾਨ ਗਲਤੀ"
+
+#: ../daemon/gvfsbackendcdda.c:818
+#, c-format
+msgid "No such file"
+msgstr "ਏਦਾਂ ਦੀ ਕੋਈ ਫਾਇਲ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendcdda.c:825 ../daemon/gvfsbackendcomputer.c:573
+#: ../daemon/gvfsbackenddnssd.c:345 ../daemon/gvfsbackendftp.c:1765
+#: ../daemon/gvfsbackendnetwork.c:590 ../daemon/gvfsbackendsmbbrowse.c:799
+#: ../daemon/gvfsbackendsmbbrowse.c:866 ../daemon/gvfsbackendsmbbrowse.c:1037
+#: ../daemon/gvfsbackendsmbbrowse.c:1111
+#, c-format
+msgid "File doesn't exist"
+msgstr "ਫਾਇਲ ਮੌਜੂਦ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendcdda.c:832
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ਫਾਈਲ ਮੌਜੂਦ ਨਹੀਂ ਹੈ ਜਾਂ ਇੱਕ ਆਡੀਓ ਟਰੈਕ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendcdda.c:938
+msgid "Audio CD Filesystem Service"
+msgstr "ਆਡੀਓ CD ਫਾਈਲ-ਸਿਸਟਮ ਸਰਵਿਸ"
+
+#: ../daemon/gvfsbackendcomputer.c:180 ../daemon/gvfsbackendcomputer.c:694
+msgid "Computer"
+msgstr "ਕੰਪਿਊਟਰ"
+
+#: ../daemon/gvfsbackendcomputer.c:467
+msgid "Filesystem"
+msgstr "ਫਾਇਲ ਸਿਸਟਮ"
+
+#: ../daemon/gvfsbackendcomputer.c:591 ../daemon/gvfsbackendobexftp.c:739
+#: ../daemon/gvfsbackendtrash.c:635
+msgid "Can't open directory"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendcomputer.c:595 ../daemon/gvfsbackendcomputer.c:733
+msgid "Can't open mountable file"
+msgstr "ਮਾਊਂਟ-ਯੋਗ ਫਾਈਲ ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ"
+
+#: ../daemon/gvfsbackendcomputer.c:781
+#, c-format
+msgid "Internal error: %s"
+msgstr "ਅੰਦਰੂਨੀ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:813 ../daemon/gvfsbackendcomputer.c:927
+msgid "Can't mount file"
+msgstr "ਫਾਈਲ ਮਾਊਂਟ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ"
+
+#: ../daemon/gvfsbackendcomputer.c:822
+msgid "No media in the drive"
+msgstr "ਡਰਾਈਵ ਵਿੱਚ ਮੀਡਿਆ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendcomputer.c:879 ../daemon/gvfsbackendcomputer.c:970
+#: ../daemon/gvfsbackendcomputer.c:1070
+msgid "Not a mountable file"
+msgstr "ਇੱਕ ਮਾਊਂਟ-ਯੋਗ ਫਾਈਲ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendcomputer.c:985
+msgid "Can't unmount file"
+msgstr "ਫਾਈਲ ਅਣ-ਮਾਊਂਟ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendcomputer.c:1101
+msgid "Can't eject file"
+msgstr "ਫਾਈਲ ਰੱਦ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ"
+
+#: ../daemon/gvfsbackenddav.c:283 ../daemon/gvfsbackenddav.c:1259
+#: ../daemon/gvfsbackenddav.c:1720 ../daemon/gvfsbackendhttp.c:215
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackenddav.c:299
+msgid "Could not parse response"
+msgstr "ਜਵਾਬ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"
+
+#: ../daemon/gvfsbackenddav.c:308
+msgid "Empty response"
+msgstr "ਖਾਲੀ ਜਵਾਬ"
+
+#: ../daemon/gvfsbackenddav.c:315
+msgid "Unexpected reply from server"
+msgstr "ਸਰਵਰ ਤੋਂ ਗਲਤ ਜਵਾਬ"
+
+#: ../daemon/gvfsbackenddav.c:918 ../daemon/gvfsbackenddav.c:1378
+#, c-format
+msgid "Response invalid"
+msgstr "ਗਲਤ ਜਵਾਬ"
+
+#: ../daemon/gvfsbackenddav.c:1062
+msgid "WebDAV share"
+msgstr "WebDAV ਸ਼ੇਅਰ"
+
+#: ../daemon/gvfsbackenddav.c:1064
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s ਲਈ ਪਾਸਵਰਡ ਦਿਓ"
+
+#: ../daemon/gvfsbackenddav.c:1067
+msgid "Please enter proxy password"
+msgstr "ਆਪਣਾ ਪਰਾਕਸੀ ਪਾਸਵਰਡ ਦਿਓ ਜੀ"
+
+#: ../daemon/gvfsbackenddav.c:1176 ../daemon/gvfsbackendhttp.c:292
+#: ../daemon/gvfsbackendobexftp.c:592 ../daemon/gvfsbackendobexftp.c:603
+#: ../daemon/gvfsbackendsmb.c:594
+msgid "Invalid mount spec"
+msgstr "ਗਲਤ ਮਾਊਂਟ ਹਦਾਇਤਾਂ"
+
+#: ../daemon/gvfsbackenddav.c:1263 ../daemon/gvfsbackenddav.c:1267
+msgid "Not a WebDAV enabled share"
+msgstr "ਇੱਕ WebDAV ਯੋਗ ਕੀਤਾ ਸ਼ੇਅਰ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackenddav.c:1334 ../daemon/gvfsbackenddav.c:1409
+msgid "Could not create request"
+msgstr "ਮੰਗ ਬਣਾਈ ਨਹੀਂ ਜਾ ਸਕੀ ਹੈ"
+
+#: ../daemon/gvfsbackenddav.c:1474 ../daemon/gvfsbackendsmb.c:1726
+msgid "Target file already exists"
+msgstr "ਟਾਰਗੇਟ ਫਾਈਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ"
+
+#: ../daemon/gvfsbackenddav.c:1544 ../daemon/gvfsbackendsftp.c:2689
+#: ../daemon/gvfsbackendsmb.c:982
+msgid "The file was externally modified"
+msgstr "ਫਾਈਲ ਬਾਹਰੋ ਸੋਧੀ ਗਈ ਹੈ"
+
+#: ../daemon/gvfsbackenddav.c:1575 ../daemon/gvfsbackendsmb.c:1020
+#: ../daemon/gvfsbackendsmb.c:1743
+msgid "Backup file creation failed"
+msgstr "ਬੈਕਅੱਪ ਫਾਈਲ ਬਣਉਣ ਫੇਲ੍ਹ ਹੈ"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "ਫਾਈਲ ਜਾਂ ਡਾਇਰੈਕਟਰੀ ਮਾਨੀਟਰ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "ਨੈੱਟਵਰਕ"
+
+#: ../daemon/gvfsbackendftp.c:183
+msgid "Accounts are unsupported"
+msgstr "ਅਕਾਊਂਟ ਗ਼ੈਰ-ਸਹਾਇਕ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:187
+msgid "Host closed connection"
+msgstr "ਹੋਸਟ ਨੇ ਕੁਨੈਕਸ਼ਨ ਬੰਦ ਕਰ ਦਿੱਤਾ"
+
+#: ../daemon/gvfsbackendftp.c:191
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "ਡਾਟਾ ਕੁਨੈਕਸ਼ਨ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ। ਸ਼ਾਇਦ ਤੁਹਾਡੀ ਫਾਇਰਵਾਲ ਓਹਲੇ ਕਰ ਰਹੀ ਹੈ?"
+
+#: ../daemon/gvfsbackendftp.c:195
+msgid "Data connection closed"
+msgstr "ਡਾਟਾ ਕੁਨੈਕਸ਼ਨ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:201
+msgid "File unavailable"
+msgstr "ਫਾਈਲ ਉਪਲੱਬਧ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendftp.c:205
+msgid "Operation failed"
+msgstr "ਓਪਰੇਸ਼ਨ ਫੇਲ੍ਹ ਹੋਇਆ"
+
+#: ../daemon/gvfsbackendftp.c:210
+msgid "No space left on server"
+msgstr "ਸਰਵਰ ਉੱਤੇ ਥਾਂ ਬਾਕੀ ਨਹੀਂ ਬਚੀ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:218
+msgid "Operation unsupported"
+msgstr "ਓਪਰੇਸ਼ਨ ਗ਼ੈਰ-ਸਹਾਇਕ"
+
+#: ../daemon/gvfsbackendftp.c:222 ../daemon/gvfsbackendsftp.c:261
+msgid "Permission denied"
+msgstr "ਅਧਿਕਾਰ ਪਾਬੰਦੀ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:226
+msgid "Page type unknown"
+msgstr "ਪੇਜ਼ ਟਾਈਪ ਅਣਜਾਣ"
+
+#: ../daemon/gvfsbackendftp.c:230 ../daemon/gvfsbackendftp.c:1840
+#, c-format
+msgid "Invalid filename"
+msgstr "ਗਲਤ ਫਾਈਲ ਨਾਂ"
+
+#: ../daemon/gvfsbackendftp.c:234 ../daemon/gvfsbackendftp.c:312
+#: ../daemon/gvfsbackendftp.c:336 ../daemon/gvfsbackendftp.c:349
+#: ../daemon/gvfsbackendftp.c:365 ../daemon/gvfsbackendftp.c:648
+#, c-format
+msgid "Invalid reply"
+msgstr "ਗਲਤ ਜਵਾਬ"
+
+#: ../daemon/gvfsbackendftp.c:461
+#, c-format
+msgid "broken transmission"
+msgstr "ਟੁੱਟੀ ਟਰਾਂਸਮਿਸ਼ਨ"
+
+#: ../daemon/gvfsbackendftp.c:553 ../daemon/gvfsbackendftp.c:666
+#, c-format
+msgid "Could not connect to host"
+msgstr "ਹੋਸਟ ਨਾਲ ਕੁਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:906
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s ਉੱਤੇ ftp ਲਈ ਪਾਸਵਰਡ ਦਿਓ"
+
+#: ../daemon/gvfsbackendftp.c:925 ../daemon/gvfsbackendsftp.c:834
+msgid "Password dialog cancelled"
+msgstr "ਪਾਸਵਰਡ ਡਾਈਲਾਗ ਰੱਦ ਕੀਤਾ ਗਿਆ"
+
+#: ../daemon/gvfsbackendftp.c:977
+#, c-format
+msgid "ftp on %s"
+msgstr "%s ਉੱਤੇ ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:983
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s ਉੱਤੇ %s ਵਾਂਗ ftp"
+
+#: ../daemon/gvfsbackendftp.c:1015 ../daemon/gvfsbackendsftp.c:1411
+msgid "No hostname specified"
+msgstr "ਕੋਈ ਹੋਸਟ-ਨਾਂ ਨਹੀਂ ਦਿੱਤਾ"
+
+#: ../daemon/gvfsbackendftp.c:1221 ../daemon/gvfsbackendftp.c:1931
+msgid "backups not supported yet"
+msgstr "ਬੈਕਅੱਪ ਹਾਲੇ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:1436 ../daemon/gvfsbackendftp.c:1636
+#, c-format
+msgid "filename too long"
+msgstr "ਫਾਈਲ-ਨਾਂ ਲੰਮਾ ਹੈ"
+
+#: ../daemon/gvfsbackendftp.c:1950
+#, c-format
+msgid "Invalid destination filename"
+msgstr "ਗਲਤ ਟਿਕਾਣਾ ਫਾਈਲ ਨਾਂ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:234
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "ਡਿਜ਼ੀਟਲ ਕੈਮਰਾ (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:379 ../hal/ghalvolume.c:390
+#, c-format
+msgid "%s Camera"
+msgstr "%s ਕੈਮਰਾ"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:382 ../hal/ghalvolume.c:385
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ਆਡੀਓ ਪਲੇਅਰ"
+
+#: ../daemon/gvfsbackendgphoto2.c:391 ../hal/ghalvolume.c:402
+msgid "Camera"
+msgstr "ਕੈਮਰਾ"
+
+#: ../daemon/gvfsbackendgphoto2.c:393 ../hal/ghalvolume.c:398
+msgid "Audio Player"
+msgstr "ਆਡੀਓ ਪਲੇਅਰ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:613
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s ਉੱਤੇ gphoto2 ਮਾਊਂਟ"
+
+#: ../daemon/gvfsbackendhttp.c:211
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP ਕਲਾਇਟ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendhttp.c:550 ../daemon/gvfsbackendsftp.c:1751
+#: ../daemon/gvfsbackendsmb.c:1229 ../daemon/gvfsbackendtrash.c:960
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr "(ਗਲਤ ਇੰਕੋਡਿੰਗ)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਨੋਟੀਫਿਕੇਸ਼ਨ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:694
+msgid "Windows Network"
+msgstr "ਵਿੰਡੋਜ਼ ਨੈੱਟਵਰਕ"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "ਲੋਕਲ ਨੈੱਟਵਰਕ"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "ਨੈੱਟਵਰਕ ਟਿਕਾਣਾ ਮਾਨੀਟਰ"
+
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:431 ../daemon/gvfsbackendsmb.c:513
+#: ../daemon/gvfsbackendsmb.c:1222
+#, c-format
+msgid "%s on %s"
+msgstr "%s ਉੱਤੇ %s"
+
+#: ../daemon/gvfsbackendsftp.c:253
+msgid "ssh program unexpectedly exited"
+msgstr "ssh ਪਰੋਗਰਾਮ ਅਚਾਨਕ ਖਤਮ ਹੋ ਗਿਆ"
+
+#: ../daemon/gvfsbackendsftp.c:268
+msgid "Hostname not known"
+msgstr "ਹੋਸਟ-ਨਾਂ ਪਤਾ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendsftp.c:275
+msgid "No route to host"
+msgstr "ਹੋਸਟ ਲਈ ਰਾਊਟ ਨਹੀਂ"
+
+#: ../daemon/gvfsbackendsftp.c:282
+msgid "Connection refused by server"
+msgstr "ਸਰਵਰ ਨੇ ਕੁਨੈਕਸ਼ਨ ਤੋਂ ਇਨਕਾਰ ਕੀਤਾ ਹੈ"
+
+#: ../daemon/gvfsbackendsftp.c:289
+msgid "Host key verification failed"
+msgstr "ਹੋਸਟ ਕੁੰਜੀ ਵੇਰੀਫਿਕੇਸ਼ਨ ਫੇਲ੍ਹੀ ਹੋਈ"
+
+#: ../daemon/gvfsbackendsftp.c:372
+msgid "Unable to spawn ssh program"
+msgstr "ssh ਪਰੋਗਰਾਮ ਸਵੈਪ ਕਰਨ ਲਈ ਅਸਮਰੱਥ"
+
+#: ../daemon/gvfsbackendsftp.c:388
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh ਪਰੋਗਰਾਮ ਸਵੈਪ ਕਰਨ ਲਈ ਅਸਮਰੱਥ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:491 ../daemon/gvfsbackendsftp.c:743
+msgid "Timed out when logging in"
+msgstr "ਲਾਗਇਨ ਕਰਨ ਦੌਰਾਨ ਟਾਈਮ ਆਉਟ"
+
+#: ../daemon/gvfsbackendsftp.c:819
+msgid "Enter passphrase for key"
+msgstr "ਕੁੰਜੀ ਲਈ ਪ੍ਹੈਰਾ ਦਿਓ"
+
+#: ../daemon/gvfsbackendsftp.c:821
+msgid "Enter password"
+msgstr "ਪਾਸਵਰਡ ਦਿਓ"
+
+#: ../daemon/gvfsbackendsftp.c:881
+msgid "Can't send password"
+msgstr "ਪਾਸਵਰਡ ਭੇਜਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"
+
+#: ../daemon/gvfsbackendsftp.c:889
+msgid "Log In Anyway"
+msgstr "ਕਿਵੇਂ ਵੀ ਲਾਗਇਨ"
+
+#: ../daemon/gvfsbackendsftp.c:889
+msgid "Cancel Login"
+msgstr "ਲਾਗਇਨ ਰੱਦ ਕਰੋ"
+
+#: ../daemon/gvfsbackendsftp.c:899
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:919
+msgid "Login dialog cancelled"
+msgstr "ਲਾਗਇਨ ਡਾਈਲਾਗ ਰੱਦ ਕੀਤਾ ਗਿਆ"
+
+#: ../daemon/gvfsbackendsftp.c:939
+msgid "Can't send host identity confirmation"
+msgstr "ਹੋਸਟ ਪਛਾਣ ਜਾਣਕਾਰੀ ਭੇਜੀ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendsftp.c:1330 ../daemon/gvfsbackendsftp.c:1353
+msgid "Protocol error"
+msgstr "ਪਰੋਟੋਕਾਲ ਗਲਤੀ"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1377
+#, c-format
+msgid "sftp on %s"
+msgstr "%s ਉੱਤੇ sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1401
+msgid "Unable to find supported ssh command"
+msgstr "ssh ਕਮਾਂਡ ਲਈ ਸਹਿਯੋਗ ਲੱਭਣ ਲਈ ਅਸਮਰੱਥ"
+
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1763
+#, c-format
+msgid "/ on %s"
+msgstr "%s ਉੱਤੇ /"
+
+#: ../daemon/gvfsbackendsftp.c:1827
+msgid "File is directory"
+msgstr "ਫਾਈਲ ਡਾਇਰੈਕਟਰੀ ਹੈ"
+
+#: ../daemon/gvfsbackendsftp.c:1836
+msgid "Failure"
+msgstr "ਫੇਲ੍ਹ"
+
+#: ../daemon/gvfsbackendsftp.c:1901 ../daemon/gvfsbackendsftp.c:1963
+#: ../daemon/gvfsbackendsftp.c:1974 ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2151
+#: ../daemon/gvfsbackendsftp.c:2199 ../daemon/gvfsbackendsftp.c:2278
+#: ../daemon/gvfsbackendsftp.c:2389 ../daemon/gvfsbackendsftp.c:2430
+#: ../daemon/gvfsbackendsftp.c:2482 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2573 ../daemon/gvfsbackendsftp.c:2727
+#: ../daemon/gvfsbackendsftp.c:2753 ../daemon/gvfsbackendsftp.c:2810
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:3149
+#: ../daemon/gvfsbackendsftp.c:3278 ../daemon/gvfsbackendsftp.c:3311
+#: ../daemon/gvfsbackendsftp.c:3412 ../daemon/gvfsbackendsftp.c:3453
+#: ../daemon/gvfsbackendsftp.c:3509 ../daemon/gvfsbackendsftp.c:3545
+#: ../daemon/gvfsbackendsftp.c:3579 ../daemon/gvfsbackendsftp.c:3594
+#: ../daemon/gvfsbackendsftp.c:3613
+msgid "Invalid reply received"
+msgstr "ਗਲਤ ਜਵਾਬ ਮਿਲਿਆ"
+
+#: ../daemon/gvfsbackendsftp.c:2220
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "ਬੈਕਅੱਪ ਫਾਈਲ ਬਣਾਉਣ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2635
+msgid "Unable to create temporary file"
+msgstr "ਆਰਜ਼ੀ ਡਾਇਰੈਕਟਰੀ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:214
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%2$s ਉੱਤੇ %1$s ਸ਼ੇਅਰ ਵਾਸਤੇ ਪਾਸਵਰਡ ਲੋੜੀਦਾ ਹੈ"
+
+#: ../daemon/gvfsbackendsmb.c:465 ../daemon/gvfsbackendsmb.c:505
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "ਅੰਦਰੂਨੀ ਗਲਤੀ (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:560
+msgid "Failed to mount Windows share"
+msgstr "ਵਿੰਡੋਜ਼ ਸ਼ੇਅਰ ਮਾਊਂਟ ਕਰਨ ਲਈ ਫੇਲ੍ਹ"
+
+#: ../daemon/gvfsbackendsmb.c:685 ../daemon/gvfsbackendsmb.c:1116
+msgid "Unsupported seek type"
+msgstr "ਗ਼ੈਰ-ਸਹਾਇਕ ਸੀਕ ਟਾਈਪ"
+
+#: ../daemon/gvfsbackendsmb.c:1170
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "ਬੈਕਅੱਪ ਫਾਈਲ ਬਣਾਉਣਾ ਫੇਲ੍ਹ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1627
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "ਫਾਈਲ ਹਟਾਉਣ 'ਚ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1691
+#, c-format
+msgid "Error moving file: %s"
+msgstr "ਫਾਈਲ ਹਿਲਾਉਣ 'ਚ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1715
+msgid "Can't move directory over directory"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਉੱਤੇ ਡਾਇਰੈਕਟਰੀ ਭੇਜੀ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendsmb.c:1763
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "ਟਾਰਗੇਟ ਫਾਈਲ ਹਟਾਉਣ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1787
+msgid "Can't recursively move directory"
+msgstr "ਡਾਇਰੈਕਟਰੀ ਲਗਾਤਾਰ ਭੇਜੀ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendsmb.c:1850
+msgid "Windows Shares Filesystem Service"
+msgstr "ਵਿੰਡੋਜ਼ ਸ਼ੇਅਰ ਫਾਈਲ-ਸਿਸਟਮ ਸਰਵਿਸ"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:702
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s ਉੱਤੇ ਵਿੰਡੋਜ਼ ਸ਼ੇਅਰ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:794 ../daemon/gvfsbackendsmbbrowse.c:840
+msgid "The file is not a mountable"
+msgstr "ਫਾਈਲ ਮਾਊਂਟ-ਯੋਗ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:862
+msgid "Not a regular file"
+msgstr "ਰੈਗੂਲਰ ਫਾਇਲ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1107
+msgid "Not a directory"
+msgstr "ਇੱਕ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1219
+msgid "Windows Network Filesystem Service"
+msgstr "ਵਿੰਡੋਜ਼ ਨੈੱਟਵਰਕ ਫਾਈਲ-ਸਿਸਟਮ ਸਰਵਿਸ"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:599 ../daemon/gvfsbackendtrash.c:1188
+msgid "Trash"
+msgstr "ਰੱਦੀ"
+
+#: ../daemon/gvfsbackendtrash.c:970
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (ਰੱਦੀ ਵਿੱਚ)"
+
+#: ../daemon/gvfsbackendtrash.c:1289
+msgid "Can't delete trash"
+msgstr "ਰੱਦੀ ਹਟਾਈ ਨਹੀਂ ਜਾ ਸਕਦੀ"
+
+#: ../daemon/gvfsbackendtrash.c:1636 ../daemon/gvfsbackendtrash.c:1711
+msgid "Trash directory notification not supported"
+msgstr "ਰੱਦੀ ਡਾਇਰੈਕਟਰੀ ਨੋਟੀਫਿਕੇਸ਼ਨ ਸਹਾਇਕ ਨਹੀਂ ਹ"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "ਗਲਤ ਬੈਕਅੱਪ ਟਾਈਪ"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd ਭੇਜਣ ਦੌਰਾਨ ਗਲਤੀ: %s"
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:119
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:169 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:154
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "ਬੈਕਐਂਡ ਰਾਹੀਂ ਓਪਰੇਸ਼ਨ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "ਸਿਮਲਿੰਕ ਬੈਕਐਂਡ ਵਲੋਂ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/gvfsjobsetattribute.c:123
+msgid "Invalid dbus message"
+msgstr "ਗਲਤ ਡੀਬੱਸ ਸੁਨੇਹਾ"
+
+#: ../daemon/main.c:47
+msgid "Replace old daemon."
+msgstr "ਪੁਰਾਣੀ ਡੈਮਨ ਬਦਲੋ।"
+
+#: ../daemon/main.c:48
+msgid "Don't start fuse."
+msgstr "fuse ਸਟਾਰਟ ਨਾ ਕਰੋ।"
+
+#: ../daemon/main.c:60
+msgid "GVFS Daemon"
+msgstr "GVFS ਡੈਮਨ"
+
+#: ../daemon/main.c:63
+msgid "Main daemon for GVFS"
+msgstr "GVFS ਲਈ ਮੇਨ ਡੈਮਨ"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:74
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:76 ../programs/gvfs-cat.c:167 ../programs/gvfs-open.c:135
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ \"%s --help\" ਵਰਤੋਂ"
+
+#: ../daemon/mount.c:372
+msgid "Invalid arguments from spawned child"
+msgstr "spawned child ਤੋਂ ਗਲਤ ਆਰਗੂਮੈਂਟ"
+
+#: ../daemon/mount.c:662
+#, c-format
+msgid "Automount failed: %s"
+msgstr "ਆਟੋ-ਮਾਊਂਟ ਫੇਲ੍ਹ: %s"
+
+#: ../daemon/mount.c:707
+msgid "The specified location is not mounted"
+msgstr "ਦਿੱਤਾ ਟਿਕਾਣਾ ਮਾਊਂਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"
+
+#: ../daemon/mount.c:712
+msgid "The specified location is not supported"
+msgstr "ਦਿੱਤਾ ਟਿਕਾਣਾ ਸਹਾਇਕ ਨਹੀਂ ਹੈ"
+
+#: ../daemon/mount.c:875
+msgid "Location is already mounted"
+msgstr "ਟਿਕਾਣਾ ਪਹਿਲਾਂ ਹੀ ਮਾਊਂਟ ਹੈ"
+
+#: ../daemon/mount.c:883
+msgid "Location is not mountable"
+msgstr "ਟਿਕਾਣਾ ਮਾਊਂਟ-ਯੋਗ ਨਹੀਂ ਹੈ"
+
+#: ../hal/ghaldrive.c:142
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../hal/ghaldrive.c:144
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../hal/ghaldrive.c:146
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../hal/ghaldrive.c:150
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../hal/ghaldrive.c:152
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../hal/ghaldrive.c:154
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../hal/ghaldrive.c:156
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../hal/ghaldrive.c:158
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../hal/ghaldrive.c:160
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../hal/ghaldrive.c:163
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../hal/ghaldrive.c:166
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../hal/ghaldrive.c:168
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../hal/ghaldrive.c:170
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../hal/ghaldrive.c:172
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../hal/ghaldrive.c:174
+msgid "Blu-ray"
+msgstr "ਬਲਿਊ-ਰੇ"
+
+#: ../hal/ghaldrive.c:176
+msgid "Blu-ray-R"
+msgstr "ਬਲਿਊ-ਰੇ-R"
+
+#: ../hal/ghaldrive.c:178
+msgid "Blu-ray-RE"
+msgstr "ਬਲਿਊ-ਰੇ-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../hal/ghaldrive.c:184
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s ਡਰਾਈਵ"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../hal/ghaldrive.c:190
+#, c-format
+msgid "%s Drive"
+msgstr "%s ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:194
+msgid "Floppy Drive"
+msgstr "ਫਲਾਪੀ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:200
+msgid "Software RAID Drive"
+msgstr "ਸਾਫਟਵੇਅਰ RAID ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:202
+msgid "USB Drive"
+msgstr "USB ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:204
+msgid "ATA Drive"
+msgstr "ATA ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:206
+msgid "SCSI Drive"
+msgstr "SCSI ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:208
+msgid "FireWire Drive"
+msgstr "ਫਾਇਰਵੇਅਰ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:212
+msgid "Tape Drive"
+msgstr "ਟੇਪ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:214
+msgid "CompactFlash Drive"
+msgstr "ਕੰਪੈਕਟ-ਫਲੈਸ਼ ਡਰਾਇਵ"
+
+#: ../hal/ghaldrive.c:216
+msgid "MemoryStick Drive"
+msgstr "ਮੈਮੋਰੀ-ਸਟਿੱਕ ਡਰਾਇਵ"
+
+#: ../hal/ghaldrive.c:218
+msgid "SmartMedia Drive"
+msgstr "ਸਮਾਰਟ-ਮੀਡਿਆ ਡਰਾਇਵ"
+
+#: ../hal/ghaldrive.c:220
+msgid "SD/MMC Drive"
+msgstr "SD/MMC ਡਰਾਇਵ"
+
+#: ../hal/ghaldrive.c:222
+msgid "Zip Drive"
+msgstr "ਜ਼ਿੱਪ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:224
+msgid "Jaz Drive"
+msgstr "ਜੇਜ਼ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:226
+msgid "Thumb Drive"
+msgstr "ਥੰਮ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:229
+msgid "Mass Storage Drive"
+msgstr "ਮਾਸ ਸਟੋਰੇਜ਼ ਡਰਾਈਵ"
+
+#: ../hal/ghaldrive.c:653
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "ਮੀਡਿਆ ਕੱਢਣ ਲਈ ਅਸਮਰੱਥ; ਮੀਡਿਆ ਤੋਂ ਇੱਕ ਜਾਂ ਵੱਧ ਵਾਲੀਅਮ ਰੁੱਝੇ ਹਨ।"
+
+#: ../hal/ghalmount.c:147 ../hal/ghalvolume.c:139
+msgid "CD-ROM Disc"
+msgstr "CD-ROM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:147 ../hal/ghalvolume.c:139
+msgid "Blank CD-ROM Disc"
+msgstr "ਖਾਲੀ CD-ROM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:148 ../hal/ghalvolume.c:140
+msgid "CD-R Disc"
+msgstr "CD-R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:148 ../hal/ghalvolume.c:140
+msgid "Blank CD-R Disc"
+msgstr "ਖਾਲੀ CD-R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:149 ../hal/ghalvolume.c:141
+msgid "CD-RW Disc"
+msgstr "CD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:149 ../hal/ghalvolume.c:141
+msgid "Blank CD-RW Disc"
+msgstr "ਖਾਲੀ CD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:150 ../hal/ghalmount.c:152 ../hal/ghalvolume.c:142
+#: ../hal/ghalvolume.c:144
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:150 ../hal/ghalmount.c:152 ../hal/ghalvolume.c:142
+#: ../hal/ghalvolume.c:144
+msgid "Blank DVD-ROM Disc"
+msgstr "ਖਾਲੀ DVD-ROM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:151 ../hal/ghalvolume.c:143
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:151 ../hal/ghalvolume.c:143
+msgid "Blank DVD-RAM Disc"
+msgstr "ਖਾਲੀ DVD-RAM ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:153 ../hal/ghalvolume.c:145
+msgid "DVD-RW Disc"
+msgstr "DVD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:153 ../hal/ghalvolume.c:145
+msgid "Blank DVD-RW Disc"
+msgstr "ਖਾਲੀ DVD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:154 ../hal/ghalvolume.c:146
+msgid "DVD+R Disc"
+msgstr "DVD+R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:154 ../hal/ghalvolume.c:146
+msgid "Blank DVD+R Disc"
+msgstr "ਖਾਲੀ DVD+R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:155 ../hal/ghalvolume.c:147
+msgid "DVD+RW Disc"
+msgstr "DVD+RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:155 ../hal/ghalvolume.c:147
+msgid "Blank DVD+RW Disc"
+msgstr "ਖਾਲੀ DVD+RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:156 ../hal/ghalvolume.c:148
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:156 ../hal/ghalvolume.c:148
+msgid "Blank DVD+R DL Disc"
+msgstr "ਖਾਲੀ DVD+R DL ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:157 ../hal/ghalvolume.c:149
+msgid "Blu-Ray Disc"
+msgstr "ਬਲਿਉ-ਰੇ ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:157 ../hal/ghalvolume.c:149
+msgid "Blank Blu-Ray Disc"
+msgstr "ਖਾਲੀ ਬਲਿਉ-ਰੇ ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:158 ../hal/ghalvolume.c:150
+msgid "Blu-Ray R Disc"
+msgstr "ਬਲਿਉ-ਰੇ R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:158 ../hal/ghalvolume.c:150
+msgid "Blank Blu-Ray R Disc"
+msgstr "ਖਾਲੀ ਬਲਿਉ-ਰੇ R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:159 ../hal/ghalvolume.c:151
+msgid "Blu-Ray RW Disc"
+msgstr "ਬਲਿਉ-ਰੇ RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:159 ../hal/ghalvolume.c:151
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ਖਾਲੀ ਬਲਿਉ-ਰੇ RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:160 ../hal/ghalvolume.c:152
+msgid "HD DVD Disc"
+msgstr "HD DVD ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:160 ../hal/ghalvolume.c:152
+msgid "Blank HD DVD Disc"
+msgstr "ਖਾਲੀ HD DVD ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:161 ../hal/ghalvolume.c:153
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:161 ../hal/ghalvolume.c:153
+msgid "Blank HD DVD-R Disc"
+msgstr "ਖਾਲੀ HD DVD-R ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:162 ../hal/ghalvolume.c:154
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:162 ../hal/ghalvolume.c:154
+msgid "Blank HD DVD-RW Disc"
+msgstr "ਖਾਲੀ HD DVD-RW ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:163 ../hal/ghalvolume.c:155
+msgid "MO Disc"
+msgstr "MO ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:163 ../hal/ghalvolume.c:155
+msgid "Blank MO Disc"
+msgstr "ਖਾਲੀ MO ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:164 ../hal/ghalvolume.c:156
+msgid "Disc"
+msgstr "ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:164 ../hal/ghalvolume.c:156
+msgid "Blank Disc"
+msgstr "ਖਾਲੀ ਡਿਸਕ"
+
+#: ../hal/ghalmount.c:349
+#, c-format
+msgid "%.1f kB Media"
+msgstr "%.1f kB ਮੀਡਿਆ"
+
+#: ../hal/ghalmount.c:354
+#, c-format
+msgid "%.1f MB Media"
+msgstr "%.1f MB ਮੀਡਿਆ"
+
+#: ../hal/ghalmount.c:359
+#, c-format
+msgid "%.1f GB Media"
+msgstr "%.1f GB ਮੀਡਿਆ"
+
+#: ../hal/ghalmount.c:486 ../hal/ghalvolume.c:305
+msgid "Mixed Audio/Data Disc"
+msgstr "ਮਿਕਸਡ ਆਡੀਓ/ਡਾਟਾ ਡਿਸਕ"
+
+#: ../hal/ghalvolume.c:190
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../hal/ghalvolume.c:195
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../hal/ghalvolume.c:200
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:293
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s ਇੰਕ੍ਰਿਪਟਡ ਡਾਟਾ"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../hal/ghalvolume.c:316
+#, c-format
+msgid "%s Media"
+msgstr "%s ਮੀਡਿਆ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:59
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s ਫਾਈਲ ਖੋਲ੍ਹਣ ਦੌਰਾਨ ਗਲਤੀ: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:82
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout ਲਿਖਣ ਦੌਰਾਨ ਗਲਤੀ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:94
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: ਪੜ੍ਹਨ ਦੌਰਾਨ ਗਲਤੀ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:112
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: ਬੰਦ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ: %s\n"
+
+#: ../programs/gvfs-cat.c:138
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - concatenate LOCATIONS to standard output."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:143
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:150
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:165 ../programs/gvfs-open.c:133
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ਗੁੰਮ ਟਿਕਾਣੇ"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:58
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: ਟਿਕਾਣਾ ਖੋਲ੍ਹਣ ਦੌਰਾਨ ਗਲਤੀ: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:85
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: ਐਪਲੀਕੇਸ਼ਨ ਲਾਂਚ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ: %s\n"
+
+#: ../programs/gvfs-open.c:115
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - open FILES with registered application."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:119
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "ਇਸ ਟਾਈਪ ਦੀਆਂ ਫਾਈਲਾਂ ਖੋਲ੍ਹਣ ਲਈ ਰਜਿਸਟਰ ਡਿਫਾਲਟ ਐਪਲੀਕੇਸ਼ਨ ਨਾਲ ਇਹ ਫਾਈਲ ਖੋਲ੍ਹਦਾ ਹੈ।"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "%s ਉੱਤੇ ਆਡੀਓ ਡਿਸਕ"
+
+#~ msgid "The file does not exist"
+#~ msgstr "ਫਾਇਲ ਮੌਜੂਦ ਨਹੀਂ"
+
diff --git a/trunk/po/pl.po b/trunk/po/pl.po
new file mode 100644
index 00000000..73292c32
--- /dev/null
+++ b/trunk/po/pl.po
@@ -0,0 +1,1884 @@
+# Polish translation of gvfs.
+# Copyright (C) 2007-2009 Tomasz Dominikowski
+# This file is distributed under the same license as the gvfs package.
+# Tomasz Dominikowski <tdominikowski@aviary.pl>, 2007, 2008, 2009.
+#
+# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+# Aviary.pl
+# Jeśli masz jakiekolwiek uwagi odnoszące się do tłumaczenia lub chcesz
+# pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas:
+# gnomepl@aviary.pl
+# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-13 23:59+0100\n"
+"PO-Revision-Date: 2009-03-14 00:04+0100\n"
+"Last-Translator: wadim dziedzic <wdziedzic@aviary,pl>\n"
+"Language-Team: Aviary.pl <gnomepl@aviary.pl>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Poedit-Language: Polish\n"
+"X-Poedit-Country: Poland\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Nieobsługiwana operacja, pliki znajdują się na różnych punktach montowania"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Niepoprawna wartość zwrotna od get_info"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Niepoprawna wartość zwrotna od query_info"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Nie można uzyskać opisu pliku strumienia"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Niepoprawna zwrócona wartość z funkcji open"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Nie otrzymano opisu pliku strumienia"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Niepoprawna zwrócona wartość z funkcji call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Niepoprawna zwrócona wartość z funkcji get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nie można odnaleźć zawierającego punktu montowania"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Niepoprawna nazwa pliku %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Niepoprawna zwrócona wartość z funkcji query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Niepoprawna zwrócona wartość z funkcji monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Niepoprawna zwrócona wartość z funkcji monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91
+#: ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187
+#: ../daemon/gvfschannel.c:298
+#: ../monitor/proxy/gproxydrive.c:442
+#: ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644
+#: ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538
+#: ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "Działanie zostało anulowane"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Błąd w protokole strumienia: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Koniec strumienia"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "Wyszukiwanie nie jest obsługiwane w strumieniu"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Błąd podczas uzyskiwania informacji o montowaniu: %s"
+
+#: ../client/gvfsdaemondbus.c:567
+#: ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Błąd podczas łączenia z usługą: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Niepoprawna wartość zwrotna od open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Błąd podczas tworzenia gniazda: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Błąd podczas łączenia z gniazdem: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Niepoprawny format informacji o pliku"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Niepoprawny atrybut zawartości "
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Błąd podczas inicjalizowania Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Błąd podczas tworzenia resolwera Avahi: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Błąd podczas wyznaczania usługi typu \"%s\" o nazwie \"%s\" w domenie \"%s\""
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "Błąd podczas wyznaczania usługi typu \"%s\" o nazwie \"%s\" w domenie \"%s\". Brakuje co najmniej jednego rekordu TXT. Wymagane klucze: \"%s\""
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Upłynął limit czasu wyznaczania usługi typu \"%s\" o nazwie \"%s\" w domenie \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Zniekształcony dns-sd encoded_triple \"%s\""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Nie można obsłużyć wersji %d kodowania GVfsIcon "
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Zniekształcone dane wejściowe dla GVfsIcon"
+
+#: ../daemon/daemon-main.c:76
+#: ../daemon/daemon-main.c:230
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Błąd podczas łączenia z D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:91
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Usługa systemu plików %s"
+
+#: ../daemon/daemon-main.c:110
+#, c-format
+msgid "Error: %s"
+msgstr "Błąd: %s"
+
+#: ../daemon/daemon-main.c:155
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Użycie: %s --spawner dbus-id ścieżka_obiektu"
+
+#: ../daemon/daemon-main.c:179
+#: ../daemon/daemon-main.c:197
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Użycie: %s key=wartość key=wartość ..."
+
+#: ../daemon/daemon-main.c:195
+#, c-format
+msgid "No mount type specified"
+msgstr "Nie podano typu montowania"
+
+#: ../daemon/daemon-main.c:265
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "punkt montowania dla %s już uruchomiony"
+
+#: ../daemon/daemon-main.c:276
+msgid "error starting mount daemon"
+msgstr "błąd podczas uruchamiania usługi montowania"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318
+#: ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1922
+#, c-format
+msgid "/ on %s"
+msgstr "/ na %s"
+
+#: ../daemon/gvfsbackendarchive.c:518
+#: ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1587
+msgid "No hostname specified"
+msgstr "Nie podano nazwy hosta"
+
+#: ../daemon/gvfsbackendarchive.c:529
+#: ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836
+#: ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871
+#: ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Niepoprawna specyfikacja montowania"
+
+#: ../daemon/gvfsbackendarchive.c:614
+#: ../daemon/gvfsbackendarchive.c:658
+#: ../daemon/gvfsbackendarchive.c:708
+#: ../daemon/gvfsbackendarchive.c:737
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2264
+#: ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Plik nie istnieje"
+
+#: ../daemon/gvfsbackendarchive.c:622
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1690
+#: ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:691
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Nie można otworzyć katalogu"
+
+#: ../daemon/gvfsbackendarchive.c:746
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045
+#: ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Plik nie jest katalogiem"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Nagrywanie"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nie można utworzyć tymczasowego katalogu"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:717
+#: ../daemon/gvfsbackendburn.c:743
+#: ../daemon/gvfsbackendburn.c:781
+#: ../daemon/gvfsbackendburn.c:972
+#: ../daemon/gvfsbackendburn.c:1008
+#: ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:2010
+#: ../daemon/gvfsbackendgphoto2.c:2729
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Nie ma takiego pliku lub katalogu"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Katalog nie jest pusty"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:904
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Nie można skopiować pliku na katalog"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Asystent CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:753
+#: ../daemon/gvfsbackendburn.c:789
+#: ../daemon/gvfsbackendburn.c:924
+#: ../daemon/gvfsbackendburn.c:986
+#: ../daemon/gvfsbackendburn.c:990
+#: ../daemon/gvfsbackendburn.c:1000
+#: ../daemon/gvfsbackendgphoto2.c:2803
+msgid "File exists"
+msgstr "Plik istnieje"
+
+#: ../daemon/gvfsbackendburn.c:828
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119
+#: ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Działanie nieobsługiwane przez mechanizm przetwarzający"
+
+#: ../daemon/gvfsbackendburn.c:853
+msgid "No such file or directory in target path"
+msgstr "Nie ma takiego pliku lub katalogu na ścieżce docelowej"
+
+#: ../daemon/gvfsbackendburn.c:876
+#: ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Nie można skopiować katalogu na katalog"
+
+#: ../daemon/gvfsbackendburn.c:885
+#: ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Plik docelowy istnieje"
+
+#: ../daemon/gvfsbackendburn.c:892
+#: ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Nie można rekursywnie skopiować katalogu"
+
+#: ../daemon/gvfsbackendburn.c:950
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2383
+#: ../daemon/gvfsbackendgphoto2.c:2592
+#: ../daemon/gvfsbackendgphoto2.c:2689
+#: ../daemon/gvfsbackendgphoto2.c:2782
+msgid "Not supported"
+msgstr "Nieobsługiwane"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot connect to the system bus"
+msgstr "Nie można połączyć się z szyną systemową"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1401
+msgid "Cannot create libhal context"
+msgstr "Nie można utworzyć kontekstu libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot initialize libhal"
+msgstr "Nie można zainicjować libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nie określono napędu"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Nie można odnaleźć napędu %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Napęd %s nie zawiera plików dźwiękowych"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "Punkt montowania cdda na %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325
+#: ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "Płyta CD-Audio"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1642
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "System plików jest zajęty: %d otwarty plik"
+msgstr[1] "System plików jest zajęty: %d otwarte pliki"
+msgstr[2] "System plików jest zajęty: %d otwartych plików"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nie ma pliku %s w napędzie %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Błąd od \"paranoia\" w napędzie %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Błąd podczas wyszukiwania w strumieniu w napędzie %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1698
+#, c-format
+msgid "No such file"
+msgstr "Nie ma takiego pliku"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Plik nie istnieje lub nie jest ścieżką dźwiękową"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Usługa systemu plików CD-Audio"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Komputer"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "System plików"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Nie można otworzyć montowalnego pliku"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1065
+#, c-format
+msgid "Internal error: %s"
+msgstr "Błąd wewnętrzny: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Nie można zamontować pliku"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Brak nośnika w napędzie"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "To nie jest montowalny plik"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Nie można odmontować pliku"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Nie można wysunąć pliku"
+
+#: ../daemon/gvfsbackenddav.c:561
+#: ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Błąd HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Nie można przetworzyć odpowiedzi"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Pusta odpowiedź"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Nieoczekiwana odpowiedź od serwera"
+
+#: ../daemon/gvfsbackenddav.c:1214
+#: ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Niepoprawna odpowiedź"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Zasób WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Proszę wprowadzić hasło dla %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Proszę wprowadzić hasło pośrednika sieciowego"
+
+#: ../daemon/gvfsbackenddav.c:1697
+#: ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Nie jest to zasób WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "Zasób WebDAV na %s"
+
+#: ../daemon/gvfsbackenddav.c:1789
+#: ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Nie można utworzyć żądania"
+
+#: ../daemon/gvfsbackenddav.c:1925
+#: ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289
+#: ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528
+#: ../daemon/gvfsbackendsftp.c:3793
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Plik docelowy już istnieje"
+
+#: ../daemon/gvfsbackenddav.c:1998
+#: ../daemon/gvfsbackendsftp.c:2960
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "Plik został zmodyfikowany z zewnątrz"
+
+#: ../daemon/gvfsbackenddav.c:2029
+#: ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "Utworzenie kopii zapasowej pliku nieudane"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492
+#: ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Sieć lokalna"
+
+#: ../daemon/gvfsbackenddnssd.c:736
+#: ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Nie można obserwować pliku lub katalogu."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755
+#: ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882
+#: ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Sieć"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Konta są nieobsługiwane"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Zdalny komputer zamknął połączenie"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Nie można otworzyć połączenia danych. Proszę sprawdzić ustawienia zapory sieciowej."
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Połączenie danych zamknięte"
+
+#: ../daemon/gvfsbackendftp.c:273
+#: ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Działanie nieudane"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Brak miejsca na serwerze"
+
+#: ../daemon/gvfsbackendftp.c:290
+#: ../daemon/gvfsbackendsftp.c:4104
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Działanie nieobsługiwane"
+
+#: ../daemon/gvfsbackendftp.c:294
+#: ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Dostęp zabroniony"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Rodzaj strony nieznany"
+
+#: ../daemon/gvfsbackendftp.c:302
+#: ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "Niepoprawna nazwa pliku"
+
+#: ../daemon/gvfsbackendftp.c:306
+#: ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "Niepoprawna odpowiedź"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "transmisja przerwana"
+
+#: ../daemon/gvfsbackendftp.c:713
+#: ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "Nie można połączyć się z komputerem"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Proszę wprowadzić hasło dla sftp jako %s na %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Proszę wprowadzić hasło dla ftp na %s"
+
+#: ../daemon/gvfsbackendftp.c:1525
+#: ../daemon/gvfsbackendsftp.c:887
+#: ../daemon/gvfsbackendsmb.c:606
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Okno dialogowe hasła anulowane"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp na %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp jako %s na %s"
+
+#: ../daemon/gvfsbackendftp.c:1692
+#: ../daemon/gvfsbackendsftp.c:1986
+#: ../daemon/gvfsbackendsftp.c:3784
+msgid "File is directory"
+msgstr "Plik jest katalogiem"
+
+#: ../daemon/gvfsbackendftp.c:1914
+#: ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2821
+msgid "backups not supported yet"
+msgstr "kopie zapasowe nie są jeszcze obsługiwane"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "nazwa pliku zbyt długa"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "Niepoprawna docelowa nazwa pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Katalog lub plik już istnieje"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Nie ma takiego pliku lub katalogu"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Niepoprawna nazwa pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nieobsługiwane"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Aparat cyfrowy (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832
+#: ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Aparat %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Odtwarzacz muzyki %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844
+#: ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Aparat"
+
+#: ../daemon/gvfsbackendgphoto2.c:846
+#: ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Odtwarzacz muzyki"
+
+#: ../daemon/gvfsbackendgphoto2.c:1429
+msgid "No device specified"
+msgstr "Nie określono urządzenia"
+
+#: ../daemon/gvfsbackendgphoto2.c:1446
+msgid "Cannot create gphoto2 context"
+msgstr "Nie można utworzyć kontekstu gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1456
+msgid "Error creating camera"
+msgstr "Błąd podczas tworzenia obiektu aparatu cyfrowego"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error loading device information"
+msgstr "Błąd podczas wczytywania informacji o urządzeniu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1491
+msgid "Error looking up device information"
+msgstr "Błąd podczas uzyskiwania informacji o urządzeniu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1501
+msgid "Error getting device information"
+msgstr "Błąd podczas pobierania informacji o urządzeniu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error setting up camera communications port"
+msgstr "Błąd podczas ustawiania portu komunikacji z aparatem cyfrowym"
+
+#: ../daemon/gvfsbackendgphoto2.c:1525
+msgid "Error initializing camera"
+msgstr "Błąd podczas inicjowania aparatu cyfrowego"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1539
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "Punkt montowania gphoto2 na %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "No camera specified"
+msgstr "Nie określono aparatu cyfrowego"
+
+#: ../daemon/gvfsbackendgphoto2.c:1706
+msgid "Error creating file object"
+msgstr "Błąd podczas tworzenia obiektu pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error getting file"
+msgstr "Błąd podczas pobierania pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:1731
+msgid "Error getting data from file"
+msgstr "Błąd podczas pobierania danych z pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:1788
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Zniekształcony identyfikator ikony \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1864
+#: ../daemon/gvfsbackendgphoto2.c:3053
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Błąd podczas wyszukiwania w strumieniu w aparacie cyfrowym %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2004
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "To nie jest katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2037
+msgid "Failed to get folder list"
+msgstr "Nieudane uzyskanie listy katalogów"
+
+#: ../daemon/gvfsbackendgphoto2.c:2103
+msgid "Failed to get file list"
+msgstr "Nieudane uzyskanie listy plików"
+
+#: ../daemon/gvfsbackendgphoto2.c:2395
+msgid "Error creating directory"
+msgstr "Błąd podczas tworzenia katalogu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2604
+msgid "Name already exists"
+msgstr "Nazwa już istnieje"
+
+#: ../daemon/gvfsbackendgphoto2.c:2615
+#: ../daemon/gvfsbackendgphoto2.c:3244
+msgid "New name too long"
+msgstr "Nowa nazwa jest za długa"
+
+#: ../daemon/gvfsbackendgphoto2.c:2625
+#: ../daemon/gvfsbackendgphoto2.c:3255
+msgid "Error renaming dir"
+msgstr "Błąd podczas zmieniania nazwy katalogu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2638
+#: ../daemon/gvfsbackendgphoto2.c:3268
+msgid "Error renaming file"
+msgstr "Błąd podczas zmieniania nazwy pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:2702
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Katalog \"%s\" nie jest pusty"
+
+#: ../daemon/gvfsbackendgphoto2.c:2713
+msgid "Error deleting directory"
+msgstr "Błąd podczas usuwania katalogu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2739
+msgid "Error deleting file"
+msgstr "Błąd podczas usuwania pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:2792
+msgid "Can't write to directory"
+msgstr "Nie można zapisać do katalogu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2839
+msgid "Cannot allocate new file to append to"
+msgstr "Nie można przydzielić nowego pliku, aby dodać do"
+
+#: ../daemon/gvfsbackendgphoto2.c:2854
+msgid "Cannot read file to append to"
+msgstr "Nie można odczytać pliku, aby dodać do"
+
+#: ../daemon/gvfsbackendgphoto2.c:2865
+msgid "Cannot get data of file to append to"
+msgstr "Nie można uzyskać danych pliku, aby dodać do"
+
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error writing file"
+msgstr "Błąd podczas zapisywania pliku"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (not same directory)"
+msgstr "Nieobsługiwane (nie ten sam katalog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3212
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nieobsługiwane (źródło jest katalogiem, cel jest katalogiem)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nieobsługiwane (źródłem jest katalog, celem jest istniejący plik)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nieobsługiwane (źródłem jest plik, celem jest katalog)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Błąd klienta HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1910
+#: ../daemon/gvfsbackendsmb.c:1399
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (niepoprawne kodowanie)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Powiadamianie o katalogach nie jest obsługiwane"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Sieć Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor sieci lokalnej"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656
+#: ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s na %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Brak obsługi USB. Proszę skontaktować się z dostawcą oprogramowania"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Połączenie z urządzeniem utracone"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Urządzenie wymaga aktualizacji oprogramowania"
+
+#: ../daemon/gvfsbackendsftp.c:291
+#: ../daemon/gvfsbackendsftp.c:569
+msgid "ssh program unexpectedly exited"
+msgstr "program ssh nieoczekiwanie zakończył pracę"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Nazwa hosta jest nieznana"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "Brak ścieżki do hosta"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "Odmowa połączenia z serwerem"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Uwierzytelnienie klucza hosta nieudane"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "Nie można uruchomić programu ssh"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Nie można uruchomić programu ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531
+#: ../daemon/gvfsbackendsftp.c:792
+msgid "Timed out when logging in"
+msgstr "Przekroczono czas oczekiwania podczas logowania do"
+
+#: ../daemon/gvfsbackendsftp.c:871
+msgid "Enter passphrase for key"
+msgstr "Proszę wprowadzić hasło dla klucza"
+
+#: ../daemon/gvfsbackendsftp.c:873
+msgid "Enter password"
+msgstr "Proszę wprowadzić hasło"
+
+#: ../daemon/gvfsbackendsftp.c:949
+msgid "Can't send password"
+msgstr "Nie można wysłać hasła"
+
+#: ../daemon/gvfsbackendsftp.c:957
+msgid "Log In Anyway"
+msgstr "Zaloguj mimo wszystko"
+
+#: ../daemon/gvfsbackendsftp.c:957
+msgid "Cancel Login"
+msgstr "Anuluj logowanie"
+
+#: ../daemon/gvfsbackendsftp.c:967
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Tożsamość zdalnego komputera (%s) jest nieznana.\n"
+"To się zdarza, jeśli do komputera zalogowano się po raz pierwszy.\n"
+"\n"
+"Tożsamość wysłana przez zdalny komputer to %s. Aby uzyskać całkowitą pewność dotyczącą bezpieczeństwa, należy się skontaktować z administratorem systemu."
+
+#: ../daemon/gvfsbackendsftp.c:987
+msgid "Login dialog cancelled"
+msgstr "Okno dialogowe logowania anulowane"
+
+#: ../daemon/gvfsbackendsftp.c:1007
+msgid "Can't send host identity confirmation"
+msgstr "Nie można wysłać potwierdzenia tożsamości"
+
+#: ../daemon/gvfsbackendsftp.c:1500
+#: ../daemon/gvfsbackendsftp.c:1523
+msgid "Protocol error"
+msgstr "Błąd protokołu"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1548
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp dla %s na %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1551
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp na %s"
+
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "Unable to find supported ssh command"
+msgstr "Nie można odnaleźć obsługiwanego polecenia ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1995
+msgid "Failure"
+msgstr "Nieudane"
+
+#: ../daemon/gvfsbackendsftp.c:2051
+#: ../daemon/gvfsbackendsftp.c:2130
+#: ../daemon/gvfsbackendsftp.c:2141
+#: ../daemon/gvfsbackendsftp.c:2197
+#: ../daemon/gvfsbackendsftp.c:2283
+#: ../daemon/gvfsbackendsftp.c:2333
+#: ../daemon/gvfsbackendsftp.c:2379
+#: ../daemon/gvfsbackendsftp.c:2454
+#: ../daemon/gvfsbackendsftp.c:2561
+#: ../daemon/gvfsbackendsftp.c:2601
+#: ../daemon/gvfsbackendsftp.c:2651
+#: ../daemon/gvfsbackendsftp.c:2723
+#: ../daemon/gvfsbackendsftp.c:2735
+#: ../daemon/gvfsbackendsftp.c:2793
+#: ../daemon/gvfsbackendsftp.c:2835
+#: ../daemon/gvfsbackendsftp.c:3012
+#: ../daemon/gvfsbackendsftp.c:3037
+#: ../daemon/gvfsbackendsftp.c:3092
+#: ../daemon/gvfsbackendsftp.c:3149
+#: ../daemon/gvfsbackendsftp.c:3420
+#: ../daemon/gvfsbackendsftp.c:3487
+#: ../daemon/gvfsbackendsftp.c:3622
+#: ../daemon/gvfsbackendsftp.c:3682
+#: ../daemon/gvfsbackendsftp.c:3717
+#: ../daemon/gvfsbackendsftp.c:3745
+#: ../daemon/gvfsbackendsftp.c:3853
+#: ../daemon/gvfsbackendsftp.c:3907
+#: ../daemon/gvfsbackendsftp.c:3943
+#: ../daemon/gvfsbackendsftp.c:3977
+#: ../daemon/gvfsbackendsftp.c:3992
+#: ../daemon/gvfsbackendsftp.c:4007
+#: ../daemon/gvfsbackendsftp.c:4085
+msgid "Invalid reply received"
+msgstr "Otrzymano niepoprawną odpowiedź"
+
+#: ../daemon/gvfsbackendsftp.c:2103
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Niepoprawny icon_id \"%s\" w OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2399
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Błąd podczas tworzenia kopii zapasowej: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2897
+msgid "Unable to create temporary file"
+msgstr "Nie można utworzyć tymczasowego pliku"
+
+#: ../daemon/gvfsbackendsftp.c:3779
+#: ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "Nie można przenieść katalogu na katalog"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Wymagane hasło dla zasobu %s na %s"
+
+#: ../daemon/gvfsbackendsmb.c:485
+#: ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Błąd wewnętrzny (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Zamontowanie zasobu Windows nieudane"
+
+#: ../daemon/gvfsbackendsmb.c:760
+#: ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Typ wyszukiwania nieobsługiwany"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Utworzenie pliku kopii zapasowej nieudane: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Błąd podczas usuwania pliku: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Błąd podczas przenoszenia pliku: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Błąd podczas usuwania pliku docelowego: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "Nie można rekursywnie przenieść katalogu"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Usługa systemu plików zasobów sieciowych Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Wymagane hasło dla %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Zasoby Windows na %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Nieudane uzyskanie listy udziałów z serwera"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Plik nie jest montowalny"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "To nie jest zwykły plik"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Usługa systemu plików sieci Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#: ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Katalog kosza nie może zostać usunięty"
+
+#: ../daemon/gvfsbackendtrash.c:387
+#: ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Elementy w koszu nie mogą być modyfikowane"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735
+#: ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Kosz"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Niepoprawny typ mechanizmu przetwarzającego"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Błąd podczas wysyłania fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Dowiązania symboliczne nieobsługiwane przez mechanizm przetwarzający"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Błędny komunikat dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Zamiana starej usługi."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Bez uruchamiania fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Usługa GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Główna usługa dla GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Więcej informacji: \"%s --help\""
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Niepoprawne parametry od utworzonego elementu zależnego"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatyczne montowanie nie powiodło się: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Podane położenie nie jest zamontowane"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Podane położenie nie jest obsługiwane"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Położenie jest już zamontowane"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Położenie nie jest montowalne"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Płyta CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Pusta płyta CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Płyta CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Pusta płyta CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Płyta CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Pusta płyta CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Płyta DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Pusta płyta DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Płyta DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Pusta płyta DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Płyta DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Pusta płyta DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Płyta DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Pusta płyta DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Płyta DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Pusta płyta DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Płyta DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Pusta płyta DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Płyta Blu-ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Pusta płyta Blu-ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Płyta Blu-ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Pusta płyta Blu-ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Płyta Blu-ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Pusta płyta Blu-ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Płyta HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Pusta płyta HD-DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Płyta HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Pusta płyta HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Płyta HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Pusta płyta HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Dysk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Pusty dysk MO"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Płyta"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Pusta płyta"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Napęd %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "Napęd %s"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "Stacja dyskietek"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "Programowy napęd RAID"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "Napęd USB"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "Napęd ATA"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "Napęd SCSI"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "Napęd FireWire"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "Napęd taśmowy"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "Karta CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "Karta MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "Karta SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "Karta SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Napęd Zip"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Napęd Jaz"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "Pamięć przenośna"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "Napęd pamięci masowej"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Wysunięcie nośnika nieudane; jeden lub więcej woluminów na nośniku jest zajętych."
+
+#: ../monitor/hal/ghalmount.c:159
+#: ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:164
+#: ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:169
+#: ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:323
+#: ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "Mieszana płyta CD-Audio/Dane"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336
+#: ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "Nośnik %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s zaszyfrowanych danych"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: błąd podczas otwierania pliku: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, błąd podczas zapisywania do stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: błąd podczas odczytywania: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:błąd podczas zamykania: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "POŁOŻENIE... - dołączenie POŁOŻEŃ do standardowego wyjścia."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Dołączenie plików w położeniach i odpowiedź na standardowe wyjście. Działa jak zwykłe narzędzie cat, ale używając położenia gvfs zamiast plików lokalnych: przykładowo można użyć czegoś takiego jak smb://serwer/zasób/plik.txt jako położenia do powiązania."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Uwaga: w razie potrzeby opcji formatowania -n, -T lub innych, należy tunelować przez cat."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: brakujące położenia"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: błąd podczas otwierania położenia: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: błąd podczas uruchamiania aplikacji: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "PLIKI... - otwiera PLIKi za pomocą zarejestrowanej aplikacji."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Otwiera plik(i) za pomocą domyślnej aplikacji zarejestrowanej do obsługi danego typu pliku."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "Działanie query info nie jest obsługiwane"
+#~ msgid "Query info not supported on stream"
+#~ msgstr "Wyszukiwanie nie jest obsługiwane w strumieniu"
+#~ msgid "Can't delete trash"
+#~ msgstr "Nie można opróżnić kosza"
+
+#, fuzzy
+#~ msgid "Can't pull trash"
+#~ msgstr "Nie można opróżnić kosza"
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (w koszu)"
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Powiadamianie o katalogu kosza nie jest obsługiwane"
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr ""
+#~ "Błąd podczas przedstawiania katalogów w celu uzyskania prefiksu "
+#~ "ignorowania"
+#~ msgid "Error creating port info list"
+#~ msgstr "Błąd podczas tworzenia listy portów"
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "Błąd podczas uzyskiwania informacji o portach z listy portów"
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "System plików jest zajęty: %d otwartych plików"
+#~ msgid "Error listing folders"
+#~ msgstr "Błąd podczas przedstawiania katalogów"
+#~ msgid "Error listing files in folder"
+#~ msgstr "Błąd podczas przedstawiania plików w katalogu"
+#~ msgid "File unavailable"
+#~ msgstr "Plik niedostępny"
+#~ msgid "%.1f kB Media"
+#~ msgstr "Nośnik %.1f kB"
+#~ msgid "%.1f MB Media"
+#~ msgstr "Nośnik %.1f MB"
+#~ msgid "%.1f GB Media"
+#~ msgstr "Nośnik %.1f GB"
+#~ msgid "Invalid reply from server"
+#~ msgstr "Niepoprawna odpowiedź od serwera"
+#~ msgid "File does not exist"
+#~ msgstr "Plik nie istnieje"
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Płyta CD-Audio w %s"
+#~ msgid "The file does not exist"
+#~ msgstr "Plik nie istnieje"
+#~ msgid "CD Burner"
+#~ msgstr "Nagrywarka CD"
+
diff --git a/trunk/po/pt.po b/trunk/po/pt.po
new file mode 100644
index 00000000..cb22fa0b
--- /dev/null
+++ b/trunk/po/pt.po
@@ -0,0 +1,1687 @@
+# gvfs's Portuguese translation.
+# Copyright © 2008, 2009 gvfs
+# This file is distributed under the same license as the gvfs package.
+# Duarte Loreto <happyguy_pt@hotmail.com>, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 2.26\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-25 01:45+0000\n"
+"PO-Revision-Date: 2009-02-25 01:50+0000\n"
+"Last-Translator: Duarte Loreto <happyguy_pt@hotmail.com>\n"
+"Language-Team: Portuguese <gnome_pt@yahoogroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operação não suportada, ficheiros em montagens diferentes"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Valor devolvido por get_info é inválido"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Valor devolvido por query_info é inválido"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Incapaz de obter o ficheiro descritor do fluxo"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Valor devolvido por open é inválido"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Incapaz de obter o ficheiro descritor do fluxo"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Valor devolvido por call é inválido"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Valor devolvido por get_filesystem_info é inválido"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Incapaz de encontrar o ponto de montagem"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nome de ficheiro %s inválido"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Valor devolvido por query_filesystem_info é inválido"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Valor devolvido por monitor_dir é inválido"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Valor devolvido por monitor_file é inválido"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "A operação foi cancelada"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Erro no protocolo de fluxo: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Final do fluxo"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Fluxo não suporta procura"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "A operação de consulta de informação não é suportada"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Fluxo não suporta consulta de informação"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Erro ao obter informação de montagem: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Erro ao se ligar ao daemon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Valor devolvido por open_icon_for_read é inválido"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Erro ao criar o socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Erro ao se ligar ao socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Formato de ficheiro de informação inválido"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Conteúdo da lista de informação de atributos inválido"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Erro ao inicializar o Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Erro ao criar o solucionador Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Erro ao resolver o serviço \"%s\" do \"%s\" no domínio \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Erro ao resolver o serviço \"%s\" do \"%s\" no domínio \"%s\". Faltam um "
+"ou mais registos TXT. Chaves necessárias: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Tempo expirado ao resolver o serviço \"%s\" do \"%s\" no domínio \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "encoded_triple dns-sd '%s' mal-formado"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Incapaz de manipular a versão %d da codificação GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Dados de entrada mal-formados para GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Erro ao se ligar ao D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Serviço de Sistema de Ficheiros de %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Erro: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Utilização: %s -- spawner id-dbus caminho_objecto"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Utilização: %s chave=valor chave=valor ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Nenhum tipo de montagem especificado"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "o ponto de montagem de %s já está em execução"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "Erro ao iniciar o daemon de montagem"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ em %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Nenhum nome de máquina especificado"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Especificação de montagem inválida"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Ficheiro não existe"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "O ficheiro não é um directório"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Gravar"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Incapaz de criar o directório temporário"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Ficheiro ou directório inexistente"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Directório não vazio"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Incapaz de copiar um ficheiro sobre um directório"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Criador de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Ficheiro existe"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operação não é suportada pelo motor"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Ficheiro ou directório inexistente no caminho de destino"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Incapaz de copiar um directório sobre um directório"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Ficheiro de destino já existe"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Incapaz de copiar directório recursivamente"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Não suportado"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Incapaz de se ligar ao bus de sistema"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Incapaz de criar contexto de libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Incapaz de inicializar a libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nenhuma unidade especificada"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Incapaz de encontrar a unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Unidade %s não contém quaisquer ficheiros audio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "ponto de montagem cdda em %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disco Audio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Sistema de ficheiros está ocupado: %d ficheiro aberto"
+msgstr[1] "Sistema de ficheiros está ocupado: %d ficheiros abertos"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Ficheiro %s inexistente na unidade %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Erro de 'paranoia' na unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Erro ao procurar no fluxo na unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Ficheiro inexistente"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "O ficheiro não existe ou não é uma faixa audio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Serviço de Sistema de Ficheiros de CD Áudio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computador"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistema de Ficheiros"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Incapaz de abrir o directório"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Incapaz de abrir o ficheiro montável"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Erro interno: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Incapaz de montar o ficheiro"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Nenhum media no dispositivo"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Não é um ficheiro montável"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Incapaz de desmontar o ficheiro"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Incapaz de ejectar o ficheiro"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Erro HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Incapaz de processar a resposta"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Resposta vazia"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Resposta inesperada do servidor"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Partilha WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Introduza a senha para %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Introduza a senha de proxy"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Partilha som WebDAV activo"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV em %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Incapaz de criar pedido"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Já existe o ficheiro de destino"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "O ficheiro foi alterado externamente"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Falha ao criar o ficheiro de cópia de segurança"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Rede Local"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Incapaz de monitorizar um ficheiro ou um directório."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Rede"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Não são suportadas contas"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "A máquina fechou a ligação"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Incapaz de abrir a ligação de dados. Talvez a sua firewall esteja a bloqueá-"
+"la?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Ligação de dados fechada"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Falha na operação"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Servidor sem espaço disponível"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operação não é suportada"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Permissão negada"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Tipo de página desconhecido"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nome de ficheiro inválido"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "transmissão quebrada"
+
+#: ../daemon/gvfsbackendftp.c:711 ../daemon/gvfsbackendftp.c:852
+msgid "Could not connect to host"
+msgstr "Incapaz de se ligar à máquina"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Introduza a senha de ftp do utilizador %s em %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Introduza a senha de ftp para %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Diálogo de senha cancelado"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp em %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp como %s em %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "Ficheiro é um directório"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "ainda não são suportadas cópias de segurança"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nome de ficheiro demasiado extenso"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nome de ficheiro de destino inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Directório ou ficheiro já existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Ficheiro ou directório inexistente"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Nome de ficheiro inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Não Suportado"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Câmara Digital (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Câmara %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Reprodutor Áudio %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Câmara"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Reprodutor Áudio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Nenhum dispositivo especificado"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Incapaz de criar contexto gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Erro ao criar a câmara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Erro ao ler a informação do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Erro ao procurar a informação de dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Erro ao obter a informação do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Erro ao definir o porto de comunicação da câmara"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Erro ao inicializar a câmara"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "ponto de montagem gphoto2 em %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Nenhuma câmara especificada"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Erro ao criar objecto de ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Erro ao obter o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Erro ao obter dados do ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificador de ícone '%s' mal-formado"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Erro ao procurar no fluxo na câmara %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Não é um directório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Falha ao obter a lista de pastas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Falha ao obter a lista de ficheiros"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Erro ao criar directório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Nome já existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Novo nome demasiado extenso"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Erro ao renomear directório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Erro ao renomear ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Directório '%s' não está vazio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Erro ao apagar o directório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Erro ao apagar o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Incapaz de gravar no directório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Incapaz de alocar novo ficheiro ao qual acrescentar"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Incapaz de ler o ficheiro ao qual acrescentar"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Incapaz de obter dados do ficheiro ao qual acrescentar"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Erro ao gravar o ficheiro"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Não suportado (não é o mesmo directório)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Não suportado (origem é directório, destino é directório)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Não suportado (origem é directório, destino é ficheiro existente)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Não suportado (origem é ficheiro, destino é directório)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Erro de Cliente HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codificação inválida)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Notificação de directório não suportada"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Rede Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor de Localizações na Rede"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s em %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Suporte USB inexistente. Contacte o vendedor da sua distribuição"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Perdida a ligação ao dispositivo"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Dispositivo requer uma actualização da aplicação"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Aplicação ssh terminou inesperadamente"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nome de máquina desconhecido"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Nenhum caminho para a máquina"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Ligação recusada pelo servidor"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Falha na verificação da chave da máquina"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Incapaz de iniciar aplicação ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Incapaz de iniciar aplicação ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Tempo expirou ao iniciar sessão"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Introduza a frase-senha para a chave"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Introduza a senha"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Incapaz de enviar a senha"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Ainda Assim Iniciar Sessão"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Cancelar o Início de Sessão"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"A identidade do computador remoto (%s) é desconhecida.\n"
+"Tal acontece quando inicia uma sessão num computador pela primeira vez.\n"
+"\n"
+"A identidade enviada pelo computador remoto é %s. Caso queira ter a certeza "
+"absoluta de que é seguro prosseguir, contacto o administrador de sistemas."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Diálogo de início de sessão cancelado"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Incapaz de enviar a confirmação de identidade da máquina"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Erro de protocolo"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp do utilizador %s em %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp em %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Incapaz de encontrar comando ssh suportado"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Falha"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Recebida uma resposta inválida"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id '%s' inválido em OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Erro ao criar ficheiro de cópia de segurança: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Incapaz de criar o ficheiro temporário"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Incapaz de mover um directório sobre um directório"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Senha necessária para a partilha %s em %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Erro Interno (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Falha ao montar partilha Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Tipo de procura não suportado"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Falha ao criar o ficheiro de cópia de segurança: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Erro ao apagar o ficheiro: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Erro ao mover o ficheiro: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Erro ao remover o ficheiro de destino: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Incapaz de mover directório recursivamente"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Serviço de Sistema de Ficheiros Partilhado Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Senha necessária para %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Partilha Windows em %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Falha ao obter a lista de partilhas do servidor"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "O ficheiro não é montável"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Não é um ficheiro comum"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Serviço de Sistema de Ficheiros de Rede Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "A pasta de lixo não pode ser apagada"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Os itens no lixo não podem ser alterados"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Lixo"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipo de motor inválido"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Erro ao enviar fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Atalhos não são suportados pelo motor"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Mensagem dbus inválida"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Substituir o daemon antigo."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Não iniciar o fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Daemon GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Daemon principal do GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Tente \"%s --help\" para mais informações."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Argumentos inválidos oriundos de um processo filho (spawned)"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Falha ao montar automaticamente: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "A localização especificada não está montada"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "A localização especificada não é suportada"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "A localização já se encontra montada"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "A localização não é montável"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disco CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disco CD-ROM Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disco CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disco CD-R Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disco CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disco CD-RW Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disco CVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disco DVD-ROM Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disco DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disco DVD-RAM Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disco DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disco DVD-RW Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disco DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disco DVD+R Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disco DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disco DVD+RW Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disco DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disco DVD+R DL Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disco Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disco Blu-Ray Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disco Blu-Ray R Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disco Blu-Ray RW Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disco HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disco HD DVD Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disco HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disco HD DVD-R Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disco HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disco HD DVD-RW Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disco MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disco MO Virgem"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disco"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disco Virgem"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Dispositivo %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Dispositivo %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Dispositivo de Disquette"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unidade RAID por Software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unidade USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Unidade ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Unidade SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unidade FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unidate de Fita"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unidade de Flash Compacta"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unidade de Caneta de Memória"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unidade de Smart Media"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unidade SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unidade Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unidade Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Unidade Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Dispositivo de Armazenamento"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Falha ao ejectar o media; um ou mais volumes no media estão ocupados."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disco de Áudio e Dados Misturados"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Media %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s de Dados Encriptados"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: erro ao abrir o ficheiro: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, erro ao escrever para o stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: erro ao ler: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: erro ao fechar: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCALIZAÇÃO... - concatenar LOCALIZAÇÕES na consola de saída."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatenar os ficheiros nas localizações e imprimir para a consola de saída. "
+"Funciona tal como o utilitário cat, mas utiliza a localização gvfs em vez de "
+"ficheiros locais: por exemplo, pode utilizar algo como smb://servidor/"
+"recurso/ficheiro.txt como uma localização a concatenar."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: envie o resultado para o cat caso necessite das suas opções de "
+"formatação tais como -n, -T ou outra."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: localizações inexistentes"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: erro ao abrir a localização: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: erro ao iniciar a aplicação: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FICHEIROS... - abrir FICHEIROS com a aplicação registada."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Abrir o(s) ficheiro(s) com a aplicação por omissão registada para manipular "
+"este tipo de ficheiros."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (no lixo)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Incapaz de apagar o Lixo"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Não é suportada a notificação de directório de Lixo"
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr "Erro ao listar as pastas para compreender prefixo de ignorar"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "Erro ao criar lista de informação de portos"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr ""
+#~ "Erro ao obter a informação de portos da lista de informação de portos"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "Sistema de ficheiros está ocupado: %d ficheiros abertos"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Erro ao listar as pastas"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "Erro ao listar os ficheiros nas pastas"
+
+#~ msgid "File unavailable"
+#~ msgstr "Ficheiro indisponível"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Media de %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Media de %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Media de %.1f GB"
+
+#~ msgid "File does not exist"
+#~ msgstr "Ficheiro não existe"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Disco Audio em %s"
+
+#~ msgid "The file does not exist"
+#~ msgstr "O ficheiro não existe"
+
+#~ msgid "CD Burner"
+#~ msgstr "Gravador de CD"
+
+#~ msgid "Error connecting dbus: %s\n"
+#~ msgstr "Erro ao se ligar ao dbus: %s\n"
+
+#~ msgid "No fd passing socket available"
+#~ msgstr "Nenhum socket fd de passagem disponível"
diff --git a/trunk/po/pt_BR.po b/trunk/po/pt_BR.po
new file mode 100644
index 00000000..90f60a88
--- /dev/null
+++ b/trunk/po/pt_BR.po
@@ -0,0 +1,1705 @@
+# Brazilian Portuguese translation of Gvfs
+# Copyright (C) 2000-2008 Free Software Foundation, Inc.
+# This file is distributed under the same license as the Gvfs package.
+# Enrico Nicoletto <liverig@gmail.com>, 2008.
+# Jonh Wendell <wendell@bani.com.br>, 2008.
+# Vladimir Melo <vmelo@gnome.org>, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 0.1.8\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-23 10:50-0500\n"
+"PO-Revision-Date: 2009-02-23 09:15-0300\n"
+"Last-Translator: Vladimir Melo <vmelo@gnome.org>\n"
+"Language-Team: Portuguese/Brazil <gnome-pt_br-list@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Poedit-Language: Portuguese\n"
+"X-Poedit-Country: BRAZIL\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+"Não há suporte à operação, os arquivos estão em diferentes pontos de montagem"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Valor de retorno inválido de get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Valor de retorno inválido de query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Não foi possível obter o descritor de arquivo"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Valor de retorno inválido de open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Não obteve o descritor do arquivo de fluxo"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Valor de retorno inválido de call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Valor de retorno inválido de get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Não foi localizado um ponto de montagem"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nome de arquivo %s inválido"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Valor de retorno inválido de query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Valor de retorno inválido de monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Valor de retorno inválido de monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "A operação foi cancelada"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Erro no protocolo de fluxo: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Fim do fluxo"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Não há suporte à busca no fluxo"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Não há suporte à operação de consulta"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Não há suporte às informações de consulta"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Erro ao obter as informações de montagem: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Erro ao conectar ao daemon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Valor de retorno inválido de open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Erro ao criar o soquete: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Erro ao se conectar com o soquete: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Formato de informações de arquivo inválido"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Atributo inválido da lista de conteúdo"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Erro ao inicializar o Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Erro ao criar o resolvedor do Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Erro ao resolver \"%s\" serviço \"%s\" no domínio \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Erro ao resolver \"%s\" serviço \"%s\" no domínio \"%s\". Um ou mais "
+"registros TXT estão faltando. Chaves requeridas: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Resolução de tempo limite \"%s\" serviço \"%s\" no domínio \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd encoded_triple \"%s\" defeituoso"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Não foi possível manipular a versão %d da codificação GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Dados de entrada defeituosos para GVfsIcon"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Erro ao conectar ao D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Sistema de arquivos %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Erro: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Uso: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Uso: %s chave=valor chave=valor ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Nenhum tipo de montagem especificado"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "o ponto de montagem para %s já está ativo"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "erro ao iniciar o daemon de montagem"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ em %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Nenhum nome de máquina especificado"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Especificação inválida de montagem"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "O arquivo não existe"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "O arquivo não é um diretório"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Gravação"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Não foi possível criar o diretório temporário"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Nenhum arquivo ou diretório"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Diretório não vazio"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Não foi possível copiar o arquivo sobre o diretório"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Criador de CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "O arquivo existe"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Não há suporte à operação pelo backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Nenhum arquivo ou diretório no caminho de destino"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Não foi possível copiar o diretório sobre outro diretório"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "O arquivo de destino existe"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Não foi possível copiar o diretório recursivamente"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Não há suporte"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Não foi possível conectar ao bus do sistema"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Não foi possível criar o contexto libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Não foi possível inicializar libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nenhuma unidade especificada"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Não foi possível localizar a unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Não há arquivos de áudio na unidade %s"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda montado em %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disco de Áudio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "O sistema de arquivos está ocupado: %d arquivo aberto"
+msgstr[1] "O sistema de arquivos está ocupado: %d arquivos abertos"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nenhum arquivo %s na unidade %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Erro do aplicativo 'paranoia' na unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Erro ao buscar no fluxo da unidade %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Nenhum arquivo"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "O arquivo não existe ou não é uma faixa de áudio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Serviço de sistema de arquivos de CD de Áudio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Computador"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistema de arquivos"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Não foi possível abrir o diretório"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Não foi possível abrir o arquivo de montagem"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Erro interno: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Não foi possível montar arquivo"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Nenhuma mídia na unidade"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Não é um arquivo de montagem"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Não foi possível desmontar o arquivo"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Não é possível ejetar o arquivo"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Erro de HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Não foi possível analisar a resposta"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Resposta vazia"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Resposta inesperada do servidor"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Compartilhamento WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Digite a senha para %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Digite a senha do proxy"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Não é um compartilhamento WebDAV habilitado"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV em %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Não foi possível criar a requisição"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "O arquivo de destino já existe"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "O arquivo foi modificado externamente"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Criação de arquivo de backup falhou"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Rede local"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Não foi possível monitorar o arquivo ou o diretório."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Rede"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Não há suporte às contas"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "A máquina fechou a conexão"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Não foi possível abrir a conexão de dados. O seu firewall pode evitar isso?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Conexão de dados fechada"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "A operação falhou"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Não há espaço no servidor"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Não há suporte à operação"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Permissão negada"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Tipo de página desconhecido"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nome de arquivo inválido"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:388
+#: ../daemon/gvfsbackendftp.c:413 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Resposta inválida"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmissão encerrada"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Não foi possível conectar à máquina"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Digite a senha para o ftp como %s em %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Digite a senha para o ftp em %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Diálogo de senha cancelado"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp em %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp como %s em %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "O arquivo é um diretório"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "Ainda não há suporte a backups"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nome do arquivo muito longo"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nome de arquivo de destino inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: diretório ou arquivo existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: nenhum arquivo ou diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: nome de arquivo inválido"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: não há suporte"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Câmera Digital (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Câmera %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Reprodutor de áudio %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Câmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Reprodutor de áudio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Nenhum dispositivo especificado"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Não foi possível criar o contexto gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Erro ao criar a câmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Erro ao carregar as informações do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Erro ao procurar as informações do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Erro ao obter as informações do dispositivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Erro ao configurar a porta de comunicações da câmera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Erro ao inicializar a câmera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "Ponto de montagem gphoto2 em %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Nenhuma câmera especificada"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Erro ao criar o objeto do arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Erro ao obter o arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Erro ao obter os dados do arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Identificador de ícone \"%s\" defeituoso"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Erro ao buscar no fluxo da câmera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Não é um diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Falha ao obter a lista de pastas"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Falha ao obter a lista de arquivos"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Erro ao criar o diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "O arquivo já existe"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Nome novo muito longo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Erro ao renomear o diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Erro ao renomear o arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "O diretório '%s' não está vazio"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Erro ao excluir o diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Erro ao excluir o arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Não é possível escrever para o diretório"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Não foi possível alocar o novo arquivo a ser acrescentado"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Não foi possível ler o arquivo a ser acrescentado"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Não é possível obter dados do arquivo a ser acrescentado"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Erro ao escrever arquivo"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Não há suporte (não é o mesmo diretório)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Não há suporte (src é diretório, dst é diretório)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Não há suporte (src é diretório, dst é arquivo existente)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Não há suporte (src é arquivo, dst é diretório)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Erro de cliente HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codificação inválida)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Não há suporte à notificação de diretório"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Rede Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor de localização de rede"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s em %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+"Suporte a USB faltando. Por favor, entre em contato com o fabricante do "
+"software"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "A conexão ao dispositivo foi perdida"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "O dispositivo requer uma atualização de software"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "programa ssh fechou inesperadamente"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nome de máquina desconhecido"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Sem rota para a máquina"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Conexão cancelada pelo servidor"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "A verificação da chave de máquina falhou"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Não foi possível criar o programa ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Não foi possível criar o programa ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Tempo esgotado ao efetuar o login"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Digite a frase secreta para a chave"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Digite a senha"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Não foi possível enviar a senha"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Efetuar login mesmo assim"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Cancelar login"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"A identidade do computador remoto (%s) é desconhecida.\n"
+"Isso acontece quando você se conecta a um computador pela primeira vez.\n"
+"\n"
+"A identificação enviada pelo outro computador é %s. Se você quer ter a "
+"certeza que é ou não seguro continuar, pergunte ao administrador do sistema."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Diálogo de login cancelado"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Não foi possível enviar a confirmação da identidade de máquina"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Erro de protocolo"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp para %s em %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp em %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Não foi possível localizar nenhum programa ssh com suporte"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Falha"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "A resposta recebida é inválida"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id \"%s\" inválido em OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Erro ao criar arquivo de backup: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Não foi possível criar o arquivo temporário"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Não foi possível mover o diretório sobre outro diretório"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Senha requerida para compartilhar %s em %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Erro Interno (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Falha ao montar o compartilhamento Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Não há suporte ao tipo de pesquisa"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "A criação de arquivo de backup falhou: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Erro ao excluir o arquivo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Erro ao mover o arquivo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Erro ao remover o arquivo de destino: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Não foi possível mover um diretório recursivamente"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Compartilhamentos Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Senha requerida para %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Compartilhamentos Windows em %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Falha ao recuperar a lista de compartilhamento do servidor"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Este arquivo não é um montável"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Não é um arquivo normal"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Rede Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "A pasta da lixeira não pode ser excluída"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Itens na lixeira não podem ser modificados"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Lixeira"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tipo de backend inválido"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Erro ao enviar fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Não há suporte aos links simbólicos pelo backend"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Mensagem D-Bus inválida"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Substitui o daemon atual."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Não inicia o fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Servidor GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Daemon principal para o GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Tente \"%s --help\" para mais informações."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Argumentos inválidos para um filho lançado"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "A montagem automática falhou: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "A localização especificada não está montada"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Não há suporte à localização especificada"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "A localização já está montada"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "A localização não está montada"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disco CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disco de CD-ROM vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disco Gravável CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disco Gravável CD-R Vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disco Regravável CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disco Regravável CD-RW Vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disco de DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disco de DVD-ROM vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disco de DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disco de DVD-RAM vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disco de DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disco de DVD-RW vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disco de DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disco de DVD+R vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disco de DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disco de DVD+RW vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disco de DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disco de DVD+R DL vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disco de Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disco de Blu-Ray vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disco de Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disco de Blu-Ray R vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disco de Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disco de Blu-Ray RW vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disco de HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disco de HD DVD vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disco de HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disco de HD DVD-R vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disco de HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disco de HD DVD-RW vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disco MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disco MO vazio"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disco"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disco vazio"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unidade de %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unidade de %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Drive de Disquete"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "RAID via Software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Disco USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Disco ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Disco SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Unidade FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Unidade de fita"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unidade CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unidade MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unidade SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unidade SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Disco Zip Drive"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unidade Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Unidade Thumb"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unidade de armazenamento em massa"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Falha ao ejetar mídia; um ou mais volumes na mídia estão ocupados."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disco misturado de áudio/dados"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Mídia de %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s de Dados criptografados"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: erro ao abrir o arquivo: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, erro ao escrever na saída padrão"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: erro ao ler: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:erro ao fechar: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCALIZAÇÃO... - junta (concatena) as LOCALIZAÇÕES na saída padrão."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Concatena arquivos e os imprime na saída padrão. Funciona exatamente como o "
+"tradicional cat, porém usando uma URL gvfs ao invés de arquivos locais: por "
+"exemplo,você pode usar algo como smb://servidor/compartilhamento/arquivo.txt "
+"como um arquivo para concatenar."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Nota: simplesmente faça uso do pipe (|) com o cat se você precisa das suas "
+"opções de formatação, como -n, -T ou outra qualquer."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: faltando as localizações"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: erro ao abrir a localização: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: erro ao lançar o aplicativo: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ARQUIVOS... - abre os ARQUIVOS com o aplicativo registrado."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Abre o(s) arquivo(s) com o aplicativo padrão registrado para gerenciar o "
+"tipo mime do arquivo."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (na lixeira)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "A lixeira não pode ser excluída"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Não há suporte à notificação do diretório da lixeira"
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr "Erro ao listar pastas para averiguar o prefixo de ignorado"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "Erro ao criar a lista de informações da porta"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr ""
+#~ "Erro ao obter as informações da porta da lista de informações da porta"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "O sistema de arquivos está ocupado: %d arquivos abertos"
+
+#~ msgid "Error listing folders"
+#~ msgstr "Erro ao listar as pastas"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "Erro ao listar os arquivos na pasta"
+
+#~ msgid "File unavailable"
+#~ msgstr "Arquivo indisponível"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Mídia de %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Mídia de %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Mídia de %.1f GB"
+
+#~ msgid "Invalid reply from server"
+#~ msgstr "Resposta inválida do servidor"
+
+#~ msgid "File does not exist"
+#~ msgstr "O arquivo não existe"
+
+#~ msgid "Invalid username"
+#~ msgstr "Nome de usuário inválido"
+
+#~ msgid "Invalid password"
+#~ msgstr "Senha inválida"
+
+#~ msgid "Operation cancelled"
+#~ msgstr "Operação cancelada"
+
+#~ msgid "Enter passsword for %s"
+#~ msgstr "Digite a senha para %s"
+
+#~ msgid "FTP on %s"
+#~ msgstr "FTP em %s"
+
+#~ msgid "FTP on %s:%u"
+#~ msgstr "FTP em %s:%u"
+
+#~ msgid "The file does not exist"
+#~ msgstr "O arquivo não existe"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Disco de Áudio em %s"
diff --git a/trunk/po/ro.po b/trunk/po/ro.po
new file mode 100644
index 00000000..5fdc501b
--- /dev/null
+++ b/trunk/po/ro.po
@@ -0,0 +1,1806 @@
+# Romanian translation for gvfs
+# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008
+# This file is distributed under the same license as the gvfs package.
+# Adi Roiban https://launchpad.net/~adiroiban, 2008, 2009
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-12 19:44+0000\n"
+"PO-Revision-Date: 2009-02-18 23:18+0200\n"
+"Last-Translator: Adi Roiban <adi@roiban.ro>\n"
+"Language-Team: Gnome Romanian Team <gnomero-list@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 == 0) && (n != 0))) ? 2: 1));\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operație nesuportată, fișiere pe partiții diferite"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Valoare returnată nevalidă de la „get_info”"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Valoare returnată nevalidă de la „query_info"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Nu s-a putut obține descriptorul de fișier pentru flux"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Valoare returnată nevalidă de la „open”"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Nu s-a obținut descriptorul de fișier pentru flux"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Valoare returnată nevalidă de la „call”"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Valoare returnată nevalidă de la „get_filesystem_infol”"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nu s-a putut găsi punctul de montare asociat"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Nume de fișier %s nevalid"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Valoare returnată nevalidă de la „query_filesystem_info”"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Valoare returnată nevalidă de la „monitor_dir”"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Valoare returnată nevalidă de la „monitor_file”"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Operațiunea a fost anulată"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Eroare în protocol flux: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Sfârșit de flux"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Derularea în flux nu este suportată"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Operația de interogare informații nu este suportată"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Interogarea informației nu este suportată în flux"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Eroare la obținerea informațiilor de montare: %s"
+
+#: ../client/gvfsdaemondbus.c:568
+#: ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Eroare conectare la serviciu: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Valoare returnată nevalidă pentru „open_icon_for_read”"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Eroare creare socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Eroare conectare la socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Format nevalid informații fișier"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Atribut nevalid în conținut informații fișier"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Eroare la inițializarea Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Eroare la crearea rezolvatorului Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Eroare la rezolvarea „%s” serviciu „%s” în domeniul „%s”"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "Eroare la rezolvarea „%s” serviciu „%s” în domeniul „%s”. Una sau mai multe întrări TXT lispsesc. Chei necesare: „%s”."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Timp expirat la rezolvarea „%s” serviciu „%s” în domeniul „%s”"
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Intrare dns-sd encoded_triple „%s” defectă"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Nu se poate opera versiunea %d a codării GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Date de intrare defecte pentru GVfsIcon"
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Eroare conectare la D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Serviciu sistem de fișiere %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Eroare: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Utilizare: %s --spawner dbus-id cale_obiect"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Utilizare: %s cheie=valoare cheie=valoare ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Tip montare nespecificat"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "punctul de montare pentru %s rulează deja"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "eroare la pornirea serviciului de montare"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ pe %s"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Nu ați specificat un nume de gazdă"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836
+#: ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Specificații de montare nevalide"
+
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262
+#: ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Fișier neexistent"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Fișierul nu este un director"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Scrie"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nu s-a putut crea directorul temporar"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Nu există un asemenea fișier sau director"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Directorul nu este gol"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Nu se poate copia fișierul peste director"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Creare CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Fișierul există"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operația nu este admisă de către suport"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Nu există un asemenea fișier sau director în calea specificată"
+
+#: ../daemon/gvfsbackendburn.c:877
+#: ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Nu se poate copia un director peste un alt director"
+
+#: ../daemon/gvfsbackendburn.c:886
+#: ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Fișierul destinație există deja"
+
+#: ../daemon/gvfsbackendburn.c:893
+#: ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Nu se poate copia recursiv directorul"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281
+#: ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587
+#: ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Nu este suportat"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Nu s-a putut conecta la magistrala sistemului"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Nu s-a putut crea contextul libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Nu s-a putut inițializa libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nicio unitate specificată"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Nu s-a găsit dispozitivul %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Dispozitivul %s nu conține fișiere audio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda montat în %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disc audio"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Sistemul de fișiere este ocupat: %d fișier deschis"
+msgstr[1] "Sistemul de fișiere este ocupat: %d fișiere deschise"
+msgstr[2] "Sistemul de fișiere este ocupat: %d de fișiere deschise"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nu există un asemenea fișier %s pe unitatea %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Eroare de la „paranoia” pe unitatea %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Eroare la derularea în flux pe unitatea %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Nu există un asemena fișier"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Fișierul nu există sau nu este o pistă audio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Serviciu sistem de fișiere CD Audio"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Calculator"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistem de fișiere"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Nu se poate deschide dosarul"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Nu s-a putut deschide fișierul montabil"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Eroare internă: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Nu s-a putut monta fișierul"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Nu există mediu în unitate"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Nu este un fișier montabil"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Nu se poate demonta fișierul"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Nu se poate scoate fișierul"
+
+#: ../daemon/gvfsbackenddav.c:526
+#: ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Eroare HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Nu se poate analiza răspunsul"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Răspuns gol"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Răspuns neașteptat de la server"
+
+#: ../daemon/gvfsbackenddav.c:1179
+#: ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Răspuns nevalid"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Partajare WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Introduceți parola pentru %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Introduceți parola de proxy"
+
+#: ../daemon/gvfsbackenddav.c:1662
+#: ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Partanjare fără activare WebDav"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV pe %s"
+
+#: ../daemon/gvfsbackenddav.c:1754
+#: ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Nu s-a putut crea cererea"
+
+#: ../daemon/gvfsbackenddav.c:1890
+#: ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254
+#: ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Fișierul specificat există deja"
+
+#: ../daemon/gvfsbackenddav.c:1963
+#: ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Fișierul a fost modificat de o aplicație externă"
+
+#: ../daemon/gvfsbackenddav.c:1994
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Crearea fișierului de „backup” a eșuat"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492
+#: ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Rețea locală"
+
+#: ../daemon/gvfsbackenddnssd.c:736
+#: ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Nu se poate monitoriza fișierul sau directorul."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755
+#: ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882
+#: ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Rețea"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Conturile nu sunt suportate"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Conexiune închisă de gazdă"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Nu se poate deschide conexiunea de date. Probabil este blocată de firewall?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Conexiune date închisă"
+
+#: ../daemon/gvfsbackendftp.c:271
+#: ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Operațiune eșuată"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Nu a mai rămas spațiu pe server"
+
+#: ../daemon/gvfsbackendftp.c:288
+#: ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operațiune nesuportată"
+
+#: ../daemon/gvfsbackendftp.c:292
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Acces interzis"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Tip pagină necunoscut"
+
+#: ../daemon/gvfsbackendftp.c:300
+#: ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Nume de fișier nevalid"
+
+#: ../daemon/gvfsbackendftp.c:304
+#: ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Răspuns nevalid"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "transmisiune întreruptă"
+
+#: ../daemon/gvfsbackendftp.c:710
+#: ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Nu s-a putut conecta la gazdă"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Introduceți parola ftp pentru %s pe %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Introduceți parola pentru ftp pe %s"
+
+#: ../daemon/gvfsbackendftp.c:1523
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Dialog parolă anulat"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp pe %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp ca %s pe %s"
+
+#: ../daemon/gvfsbackendftp.c:1690
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Fișierul este director"
+
+#: ../daemon/gvfsbackendftp.c:1912
+#: ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "copiile de siguranță nu sunt încă suportate"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "nume de fișier prea lung"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Nume fișier destinație nevalid"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Dosarul sau fișierul există"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Nu există un asemenea fișier sau director"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Nume fișier nevalid"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nesuportat"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Cameră digitală (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823
+#: ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Cameră %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826
+#: ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Player audio %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Cameră"
+
+#: ../daemon/gvfsbackendgphoto2.c:837
+#: ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Player audio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Niciun dispozitiv specificat"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Nu s-a putut crea contextul gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Eroare la creearea camerei"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383
+#: ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Eroare la încărcarea informațiilor pentru dispozitiv"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Eroare la căutarea informațiilor pentru dispozitiv"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Eroare la obținerea informațiilor pentru dispozitiv"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Eroare la inițializarea portului de comunicare cu camera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Eroare la inițializarea camerei"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 montat în %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Nicio cameră specificată"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Eroare la crearea obiectului fișier"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Eroare la obținerea fișierului"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Eroare la obținerea datelor din fișier"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Pictogramă identificator defectă „%s”"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772
+#: ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Eroare la derularea în flux pe camera %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Nu e un dosar"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Obținerea listei dosarelor a eșuat"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Obținerea listei de fișier a eșuat"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Eroare la creearea dosarului"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Numele există deja"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513
+#: ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Noul nume este prea lung"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Eroare la redenumirea dosarului"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Eroare la redenumirea fișierului"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Dosarul „%s” nu este gol"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Eroare la ștergerea dosarului"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Eroare la ștergerea fișierului"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Nu se poate scrie în dosar"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Nu s-a putut aloca fișierul nou pentru adăugarea la"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Nu s-a putut citi fișierul pentru adăugarea la"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Nu s-a putut obține datele fișierul pentru adăugarea la"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Eroare la scrierea fișierului"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Nesuportat (nu e același dosar)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nesuportat (sursa este dosar, destinația este dosar)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nesuportat (sursa este dosar, destinația este un fișier existent)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nesuportat (sursa este fișier, destinația este dosar)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Eroare client HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (codare nevalidă)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Notificare dosar nesuportată"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Rețea Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor locații rețea"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s pe %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Suportul USB lipsește. Contactați furnizorul software"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Conexiune la dispozitiv pierdută"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Dispozitivul necesită o actualizare software"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "program ssh terminat neașteptat"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Nume gazdă necunoscut"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Nu există rută către gazdă"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Conexiune refuzată de server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Verificare cheie gazdă eșuată"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Nu s-a putut porni programul ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Nu s-a putut porni programul ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Timpul a expirat la autentificare"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Introduceți parola pentru cheie"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Introduceți parola"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Nu s-a putut trimite parola"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Autentificați oricum"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Anulează autentificarea"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identitatea calculatorului de la distanță (%s) este necunoscută.\n"
+"Acest lucru se întâmplă când vă conectați pe acest calculator pentru prima oară.\n"
+"\n"
+"Identitatea trimisă de calculatorul de la distanță este %s. Dacă doriți să fiți absolut sigur în a continua, contactați administratorul de sistem."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Dialog autentificare anulat"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Nu se poate trimite confirmare de identificare gazdă"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Eroare de protocol"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp pentru %s pe %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp pe %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Nu s-a găsit comanda ssh suportată"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Eșuare"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721
+#: ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898
+#: ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010
+#: ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348
+#: ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512
+#: ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648
+#: ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736
+#: ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785
+#: ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "S-a primit răspuns nevalid"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Icon_id „%s” nevalid în OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Eroare la crearea fișierul copie de siguranță: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Nu s-a putut crea un fișier temporar"
+
+#: ../daemon/gvfsbackendsftp.c:3574
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Nu se poate muta un director peste un alt director"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Este necesară parola pentru partajarea %s de pe %s"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Eroare internă (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Montare partajare Windows eșuată"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Tip de căutare nesuportat"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Eroare creare fișier copie de siguranță: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Eroare la ștergerea fișierului: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Eroare la mutarea fișierului: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Eroare la ștergerea fișierului destinație: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Directorul nu se poate muta recursiv"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Serviciu sistem de fișiere partajări Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Este necesară parola pentru %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Partajare Windows pe %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Obținerea listei de partajări de pe server a eșuat"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Fișierul nu este montabil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Nu este un fișier obișnuit"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Serviciu sistem de fișiere rețea Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#: ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Dosarul gunoi nu poate fi șters"
+
+#: ../daemon/gvfsbackendtrash.c:387
+#: ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Elementele din gunoi nu pot fi modificate"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735
+#: ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Gunoi"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Tip de suport nevalid"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Eroare trimitere fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Legătură simbolică nesuportată de suport"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Mesaj dbus nevalid"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Înlocuiește serviciul vechi."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Nu porni fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Serviciu GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Serviciul prinicpal pentru GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Încercați „%s --help” pentru mai multe informații"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Argumente nevalide pentru copii lansați"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Montare automată eșuată: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Locația specificată nu este montată"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Locația specificată nu este suportată"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Locația este deja montată"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Locația nu este montabilă"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disc CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disc CD-ROM gol"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disc CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disc CD-R gol"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disc CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disc CD-RW gol"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disc DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disc DVD-ROM gol"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disc DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disc DVD-RAM gol"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disc DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disc DVD-RW gol"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disc DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disc DVD+R gol"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disc DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disc DVD+RW gol"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disc DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disc DVD+R DL gol"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disc Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disc Blu-Ray gol"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disc Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disc Blu-Ray R gol"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disc Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disc Blu-Ray RW gol"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disc HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disc HD DVD gol"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disc HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disc HD DVD-R gol"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disc HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disc HD DVD-RW gol"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disc MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disc MO gol"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disc"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disc gol"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Unitate %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Unitate %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Unitate dischetă"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Unitate RAID software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Unitate USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Dispozitiv ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Dispozitiv SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Dispozitiv FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Casetă"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Unitate CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Unitate MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Unitate SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Unitate SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Unitate Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Unitate Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Stick memorie USB"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Unitate de stocare în masă"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Scoaterea mediului a eșuat; una sau mai multe volume de pe mediu sunt ocupate"
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kO"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MO"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GO"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disc combinat audio/date"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Mediu %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s date criptate"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: eroare deschidere fișier: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, eroare scriere în ieșirea standard"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: eroare citire: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: eroare închidere: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOC... - concatenează LOCURI în ieșirea standard"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Concatenează fișiere la locații și afișează în ieșirea standard. Funcționează ca utilitarul tradițional „cat”, dar folosind locații gvfs în locul fișierelor locale: de exemplu puteți folosi smb://server/resoursă/fișier.txt ca locație pentru concatenare."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Notă: trimiteți prin „cat” în cazul în care aveți nevoie de opțiune de formatare precum -n, -T sau altele."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: lipsesc locațiile"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: eroare la deschiderea locațiilor: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: eroare lansare aplicație: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FIȘIERE... - deschide fișiere cu aplicațiile inregistrate."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Deschide fișierul (fișierele) cu aplicația implicită înregistrată pentru acest timp de fișier."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Nu se poate șterge gunoiul"
+#~ msgid "Can't pull trash"
+#~ msgstr "Nu s-a putut trage gunoiul"
+
diff --git a/trunk/po/ru.po b/trunk/po/ru.po
new file mode 100644
index 00000000..7ea7ab7f
--- /dev/null
+++ b/trunk/po/ru.po
@@ -0,0 +1,1682 @@
+# Russian translation for gvfs
+# Copyright (C) 2008 Free Software Foudnation Inc.
+# This file is distributed under the same license as the gvfs package.
+#
+# Leonid Kanter <leon@asplinux.ru>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs trunk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-03-14 23:40+0300\n"
+"PO-Revision-Date: 2009-03-14 23:24+0300\n"
+"Last-Translator: Yuriy Penkin <yuriy.penkin@gmail.com>\n"
+"Language-Team: Russian <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Действие не поддерживается, файлы на разных точках монтирования"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Функция get_info вернула неверное значение"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Функция query_info вернула неверное значение"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Не удаётся получить описание файла потока"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Функция open вернула неверное значение"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Дескриптор файла потока не был получен"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Функция call вернула неверное значение"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Функция get_filesystem_info вернула неверное значение"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Не удаётся найти точку монтирования"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Неверное имя файла %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Функция query_filesystem_info вернула неверное значение"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Получено неверное значение от функции monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Получено неверное значение от функции monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:630
+#: ../client/gdaemonfileinputstream.c:783
+#: ../client/gdaemonfileinputstream.c:901
+#: ../client/gdaemonfileinputstream.c:1149
+#: ../client/gdaemonfileinputstream.c:1391
+#: ../client/gdaemonfileoutputstream.c:506
+#: ../client/gdaemonfileoutputstream.c:681
+#: ../client/gdaemonfileoutputstream.c:873
+#: ../client/gdaemonfileoutputstream.c:1052
+#: ../daemon/gvfsbackendobexftp.c:1060 ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200 ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401 ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708 ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885 ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966 ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048 ../daemon/gvfsbackendsmb.c:1139
+#: ../daemon/gvfsbackendtest.c:91 ../daemon/gvfsbackendtest.c:124
+#: ../daemon/gvfsbackendtest.c:187 ../daemon/gvfschannel.c:298
+#: ../monitor/proxy/gproxydrive.c:442 ../monitor/proxy/gproxydrive.c:526
+#: ../monitor/proxy/gproxydrive.c:644 ../monitor/proxy/gproxymount.c:455
+#: ../monitor/proxy/gproxymount.c:538 ../monitor/proxy/gproxyvolume.c:783
+#: ../monitor/proxy/gproxyvolume.c:860
+msgid "Operation was cancelled"
+msgstr "Действие было прервано"
+
+#: ../client/gdaemonfileinputstream.c:527
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1682
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:450
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1234
+#: ../client/gdaemonfileoutputstream.c:1244
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Ошибка в протоколе потока: %s"
+
+#: ../client/gdaemonfileinputstream.c:535
+#: ../client/gdaemonfileinputstream.c:1692
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:1244
+msgid "End of stream"
+msgstr "Конец потока"
+
+#: ../client/gdaemonfileinputstream.c:1330
+#: ../client/gdaemonfileoutputstream.c:981
+msgid "Seek not supported on stream"
+msgstr "Поиск в потоке не поддерживается"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Ошибка получения информации о монтировании: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Ошибка подключения к демону: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Функция open_icon_for_read вернула неверное значение"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Ошибка создания сокета: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Ошибка подключения к сокету: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Неверный формат информации о файле"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Неверное содержимое списка информации об атрибутах."
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Ошибка при инициализации Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Ошибка при создания сервиса разрешения имён Avahi: %s"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1099
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Ошибка при разрешении имени «%s» сервиса «%s» на «%s»"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#. * - the fourth %s refers to the required TXT keys
+#.
+#: ../common/gvfsdnssdresolver.c:1125
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"Ошибка при разрешении имени «%s» сервиса «%s» на «%s». Одна или несколько TXT "
+"записей не найдены. Требуются ключи: «%s»"
+
+#. Translators:
+#. * - the first %s refers to the service type
+#. * - the second %s refers to the service name
+#. * - the third %s refers to the domain
+#.
+#: ../common/gvfsdnssdresolver.c:1142
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Истёк период ожидания «%s» сервиса «%s» на «%s»"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Неверные параметры dns-sd «%s»"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Не удалось обработать текстовое представление GVfsIcon версии %d"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Некорректные входные данные для GVfsIcon"
+
+#: ../daemon/daemon-main.c:76 ../daemon/daemon-main.c:230
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Ошибка подключения к D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:91
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Служба файловой системы %s"
+
+#: ../daemon/daemon-main.c:110
+#, c-format
+msgid "Error: %s"
+msgstr "Ошибка: %s"
+
+#: ../daemon/daemon-main.c:155
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Применение: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:179 ../daemon/daemon-main.c:197
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Применение: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:195
+#, c-format
+msgid "No mount type specified"
+msgstr "Тип монтирования не указан"
+
+#: ../daemon/daemon-main.c:265
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "точка монтирования для %s уже запущена"
+
+#: ../daemon/daemon-main.c:276
+msgid "error starting mount daemon"
+msgstr "ошибка запуска демона монтирования"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:318 ../daemon/gvfsbackendftp.c:1096
+#: ../daemon/gvfsbackendsftp.c:1922
+#, c-format
+msgid "/ on %s"
+msgstr "/ на %s"
+
+#: ../daemon/gvfsbackendarchive.c:518 ../daemon/gvfsbackendftp.c:1642
+#: ../daemon/gvfsbackendsftp.c:1587
+msgid "No hostname specified"
+msgstr "Имя узла не указано"
+
+#: ../daemon/gvfsbackendarchive.c:529 ../daemon/gvfsbackendarchive.c:558
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:648
+msgid "Invalid mount spec"
+msgstr "Неверная спецификация монтирования"
+
+#: ../daemon/gvfsbackendarchive.c:614 ../daemon/gvfsbackendarchive.c:658
+#: ../daemon/gvfsbackendarchive.c:708 ../daemon/gvfsbackendarchive.c:737
+#: ../daemon/gvfsbackendcdda.c:921 ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398 ../daemon/gvfsbackendftp.c:2264
+#: ../daemon/gvfsbackendnetwork.c:646 ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152 ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Файл не существует"
+
+#: ../daemon/gvfsbackendarchive.c:622 ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1690 ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:691 ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Не удаётся открыть каталог"
+
+#: ../daemon/gvfsbackendarchive.c:746 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1045 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Этот файл не является каталогом"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Записать"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Не удаётся создать временный каталог"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:717 ../daemon/gvfsbackendburn.c:743
+#: ../daemon/gvfsbackendburn.c:781 ../daemon/gvfsbackendburn.c:972
+#: ../daemon/gvfsbackendburn.c:1008 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:2010 ../daemon/gvfsbackendgphoto2.c:2729
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Нет такого файла или каталога"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Каталог не пустой"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:904
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Не удаётся скопировать файл поверх каталога"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Создание CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:753 ../daemon/gvfsbackendburn.c:789
+#: ../daemon/gvfsbackendburn.c:924 ../daemon/gvfsbackendburn.c:986
+#: ../daemon/gvfsbackendburn.c:990 ../daemon/gvfsbackendburn.c:1000
+#: ../daemon/gvfsbackendgphoto2.c:2803
+msgid "File exists"
+msgstr "Файл существует"
+
+#: ../daemon/gvfsbackendburn.c:828 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobqueryinforead.c:119 ../daemon/gvfsjobqueryinfowrite.c:119
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Действие не поддерживается драйвером"
+
+#: ../daemon/gvfsbackendburn.c:853
+msgid "No such file or directory in target path"
+msgstr "Нет такого файла или каталога в пути назначения"
+
+#: ../daemon/gvfsbackendburn.c:876 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Не удаётся скопировать каталог поверх каталога"
+
+#: ../daemon/gvfsbackendburn.c:885 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Файл назначения уже существует"
+
+#: ../daemon/gvfsbackendburn.c:892 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Не удаётся скопировать каталог рекурсивно"
+
+#: ../daemon/gvfsbackendburn.c:950 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2383 ../daemon/gvfsbackendgphoto2.c:2592
+#: ../daemon/gvfsbackendgphoto2.c:2689 ../daemon/gvfsbackendgphoto2.c:2782
+msgid "Not supported"
+msgstr "Не поддерживается"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot connect to the system bus"
+msgstr "Не удаётся подключиться к системной шине"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1401
+msgid "Cannot create libhal context"
+msgstr "Не удалось получить контекст libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1414
+msgid "Cannot initialize libhal"
+msgstr "Не удалось инициализировать libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Устройство не указано"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Не удаётся найти устройство %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Устройство %s не содержит звуковых файлов"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "подключение cdda на %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:325 ../monitor/hal/ghalvolume.c:225
+#: ../monitor/hal/ghalvolume.c:246
+#, c-format
+msgid "Audio Disc"
+msgstr "Звуковой диск"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1642
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Файловая система занята: %d открытый файл"
+msgstr[1] "Файловая система занята: %d открытых файла"
+msgstr[2] "Файловая система занята: %d открытых файлов"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Нет такого файла %s на устройстве %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Ошибка программы \"paranoia\" на устройстве %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Ошибка поиска в потоке на устройстве %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1698
+#, c-format
+msgid "No such file"
+msgstr "Нет такого файла"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Файл не существует или не является звуковой дорожкой"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Служба файловой системы Audio CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Компьютер"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Файловая система"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Не удаётся открыть монтируемый файл"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1065
+#, c-format
+msgid "Internal error: %s"
+msgstr "Внутренняя ошибка: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Не удаётся смонтировать файл"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "В устройстве нет диска"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Файл не является монтируемым"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Не удаётся отмонтировать файл"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Не удаётся извлечь файл"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Ошибка HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Не удаётся разобрать ответ"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Пустой ответ"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Неожиданный ответ от сервера"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Неверный ответ"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Ресурс WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Введите пароль для %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Введите пароль прокси-сервера"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Не является ресурсом WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV на %s"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Не удаётся создать запрос"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1862
+#: ../daemon/gvfsbackendftp.c:2528 ../daemon/gvfsbackendsftp.c:3793
+#: ../daemon/gvfsbackendsmb.c:1974
+msgid "Target file already exists"
+msgstr "Файл назначения уже существует"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2960
+#: ../daemon/gvfsbackendsmb.c:1108
+msgid "The file was externally modified"
+msgstr "Файл был изменён извне"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1144
+#: ../daemon/gvfsbackendsmb.c:1991
+msgid "Backup file creation failed"
+msgstr "Ошибка создания резервной копии файла"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Локальная сеть"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Не удаётся отслеживать состояние файла или каталога."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Сеть"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Учётные записи не поддерживаются"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Узел закрыл соединение"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Не удаётся установить соединение данных. Проверьте, пожалуйста, настройки "
+"брандмауэра."
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Соединение данных закрыто"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Сбой операции"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "На сервере не осталось свободного места"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4104
+#: ../daemon/gvfsbackendsmb.c:1638
+msgid "Operation unsupported"
+msgstr "Действие неподдерживается"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:299
+msgid "Permission denied"
+msgstr "Доступ запрещен"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Неизвестный тип страницы"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2374
+msgid "Invalid filename"
+msgstr "Неверное имя файла"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:389
+#: ../daemon/gvfsbackendftp.c:414 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:931
+msgid "Invalid reply"
+msgstr "Неверный ответ"
+
+#: ../daemon/gvfsbackendftp.c:549
+msgid "broken transmission"
+msgstr "сбой передачи"
+
+#: ../daemon/gvfsbackendftp.c:713 ../daemon/gvfsbackendftp.c:854
+msgid "Could not connect to host"
+msgstr "Не удаётся подключиться к узлу"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1496
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Введите пароль ftp для пользователя %s на %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1499
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Введите пароль для ftp на %s"
+
+#: ../daemon/gvfsbackendftp.c:1525 ../daemon/gvfsbackendsftp.c:887
+#: ../daemon/gvfsbackendsmb.c:606 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Диалог ввода пароля прерван"
+
+#: ../daemon/gvfsbackendftp.c:1604
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp на %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1608
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp как %s на %s"
+
+#: ../daemon/gvfsbackendftp.c:1692 ../daemon/gvfsbackendsftp.c:1986
+#: ../daemon/gvfsbackendsftp.c:3784
+msgid "File is directory"
+msgstr "Файл является каталогом"
+
+#: ../daemon/gvfsbackendftp.c:1914 ../daemon/gvfsbackendftp.c:2489
+#: ../daemon/gvfsbackendsftp.c:2821
+msgid "backups not supported yet"
+msgstr "резервные копии еще не поддерживаются"
+
+#: ../daemon/gvfsbackendftp.c:1991
+msgid "filename too long"
+msgstr "имя файла слишком длинное"
+
+#: ../daemon/gvfsbackendftp.c:2508
+msgid "Invalid destination filename"
+msgstr "Неверное имя файла назначения"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: файл или каталог не существует"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: нет такого файла или каталога"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: неверное имя файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: не поддерживается"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Цифровая камера (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "Камера %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "Звуковой проигрыватель %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Звуковой проигрыватель"
+
+#: ../daemon/gvfsbackendgphoto2.c:1429
+msgid "No device specified"
+msgstr "Устройство не указано"
+
+#: ../daemon/gvfsbackendgphoto2.c:1446
+msgid "Cannot create gphoto2 context"
+msgstr "Не удалось создать контекст gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1456
+msgid "Error creating camera"
+msgstr "Ошибка при создании объекта камеры"
+
+#: ../daemon/gvfsbackendgphoto2.c:1469 ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error loading device information"
+msgstr "Ошибка при загрузке информации об устройстве"
+
+#: ../daemon/gvfsbackendgphoto2.c:1491
+msgid "Error looking up device information"
+msgstr "Не удалось найти информацию об устройстве"
+
+#: ../daemon/gvfsbackendgphoto2.c:1501
+msgid "Error getting device information"
+msgstr "Ошибка при получении информации об устройстве"
+
+#: ../daemon/gvfsbackendgphoto2.c:1514
+msgid "Error setting up camera communications port"
+msgstr "Ошибка при установке порта для связи с камерой"
+
+#: ../daemon/gvfsbackendgphoto2.c:1525
+msgid "Error initializing camera"
+msgstr "Ошибка при инициализации камеры"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1539
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "подключение gphoto2 на %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "No camera specified"
+msgstr "Камера не определена"
+
+#: ../daemon/gvfsbackendgphoto2.c:1706
+msgid "Error creating file object"
+msgstr "Ошибка при создания объекта файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error getting file"
+msgstr "Ошибка при получении файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:1731
+msgid "Error getting data from file"
+msgstr "Ошибка при получении данных из файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:1788
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Некорректный идентификатор значка «%s»"
+
+#: ../daemon/gvfsbackendgphoto2.c:1864 ../daemon/gvfsbackendgphoto2.c:3053
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Ошибка поиска в потоке, созданном камерой %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2004 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Не является каталогом"
+
+#: ../daemon/gvfsbackendgphoto2.c:2037
+msgid "Failed to get folder list"
+msgstr "Не удалось получить список каталогов"
+
+#: ../daemon/gvfsbackendgphoto2.c:2103
+msgid "Failed to get file list"
+msgstr "Не удалось получить список файлов"
+
+#: ../daemon/gvfsbackendgphoto2.c:2395
+msgid "Error creating directory"
+msgstr "Ошибка создания каталога"
+
+#: ../daemon/gvfsbackendgphoto2.c:2604
+msgid "Name already exists"
+msgstr "Такое имя уже существует"
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3244
+msgid "New name too long"
+msgstr "Слишком длинное имя"
+
+#: ../daemon/gvfsbackendgphoto2.c:2625 ../daemon/gvfsbackendgphoto2.c:3255
+msgid "Error renaming dir"
+msgstr "Ошибка при переименовании каталога"
+
+#: ../daemon/gvfsbackendgphoto2.c:2638 ../daemon/gvfsbackendgphoto2.c:3268
+msgid "Error renaming file"
+msgstr "Ошибка при переименовании файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:2702
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Каталог «%s» не пустой"
+
+#: ../daemon/gvfsbackendgphoto2.c:2713
+msgid "Error deleting directory"
+msgstr "Ошибка при удалении каталога"
+
+#: ../daemon/gvfsbackendgphoto2.c:2739
+msgid "Error deleting file"
+msgstr "Ошибка при удалении файла"
+
+#: ../daemon/gvfsbackendgphoto2.c:2792
+msgid "Can't write to directory"
+msgstr "Не удаётся произвести запись в каталог"
+
+#: ../daemon/gvfsbackendgphoto2.c:2839
+msgid "Cannot allocate new file to append to"
+msgstr "не удалось выделить новый файл для добавления в конец"
+
+#: ../daemon/gvfsbackendgphoto2.c:2854
+msgid "Cannot read file to append to"
+msgstr "Не удалось прочитать файл для добавления в конец"
+
+#: ../daemon/gvfsbackendgphoto2.c:2865
+msgid "Cannot get data of file to append to"
+msgstr "Не удалось получить данные файла для добавления в конец"
+
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error writing file"
+msgstr "Ошибка записи в файл"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (not same directory)"
+msgstr "Не поддерживается (не тот же самый каталог)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3212
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Не поддерживается (источник - каталог, назначение - каталог)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Не поддерживается (источник - каталог, назначение - существующий файл)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Не поддерживается (источник - файл, назначение - каталог)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Ошибка клиента HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1910
+#: ../daemon/gvfsbackendsmb.c:1399 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (неверная кодировка)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Уведомление для каталогов не поддерживается"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Сеть Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Обзор сети"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:545
+#: ../daemon/gvfsbackendsmb.c:1392
+#, c-format
+msgid "%s on %s"
+msgstr "%s на %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+"Не найдена поддержка USB. Свяжитесь с вашим поставщиком программного "
+"обеспечения"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Соединение с устройством потеряно"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Устройство требует обновления программного обеспечения"
+
+#: ../daemon/gvfsbackendsftp.c:291 ../daemon/gvfsbackendsftp.c:569
+msgid "ssh program unexpectedly exited"
+msgstr "Программа ssh неожиданно завершилась"
+
+#: ../daemon/gvfsbackendsftp.c:306
+msgid "Hostname not known"
+msgstr "Имя узла неизвестно"
+
+#: ../daemon/gvfsbackendsftp.c:313
+msgid "No route to host"
+msgstr "Нет маршрута к узлу"
+
+#: ../daemon/gvfsbackendsftp.c:320
+msgid "Connection refused by server"
+msgstr "Соединение отклонено сервером"
+
+#: ../daemon/gvfsbackendsftp.c:327
+msgid "Host key verification failed"
+msgstr "Сбой проверки сертификата узла"
+
+#: ../daemon/gvfsbackendsftp.c:413
+msgid "Unable to spawn ssh program"
+msgstr "Не удаётся выполнить программу ssh"
+
+#: ../daemon/gvfsbackendsftp.c:429
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Не удаётся выполнить программу ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:531 ../daemon/gvfsbackendsftp.c:792
+msgid "Timed out when logging in"
+msgstr "Время ожидания входа в систему истекло"
+
+#: ../daemon/gvfsbackendsftp.c:871
+msgid "Enter passphrase for key"
+msgstr "Введите ключевую разу для ключа"
+
+#: ../daemon/gvfsbackendsftp.c:873
+msgid "Enter password"
+msgstr "Введите пароль"
+
+#: ../daemon/gvfsbackendsftp.c:949
+msgid "Can't send password"
+msgstr "Не удаётся отправить пароль"
+
+#: ../daemon/gvfsbackendsftp.c:957
+msgid "Log In Anyway"
+msgstr "Подключиться всё равно"
+
+#: ../daemon/gvfsbackendsftp.c:957
+msgid "Cancel Login"
+msgstr "Отменить подключение"
+
+#: ../daemon/gvfsbackendsftp.c:967
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Не удаётся проверить подлинность удалённого компьютера (%s).\n"
+"Это обычно происходит при первом подключении к компьютеру.\n"
+"\n"
+"Строка идентификации, переданная удалённым компьютером: %s. Если вы хотите "
+"быть абсолютно уверенным в безопасности подключения к этому компьютеру, "
+"обратитесь к системному администратору."
+
+#: ../daemon/gvfsbackendsftp.c:987
+msgid "Login dialog cancelled"
+msgstr "Диалог ввода пароля прерван"
+
+#: ../daemon/gvfsbackendsftp.c:1007
+msgid "Can't send host identity confirmation"
+msgstr "Не удаётся отправить подтверждение идентификации узла"
+
+#: ../daemon/gvfsbackendsftp.c:1500 ../daemon/gvfsbackendsftp.c:1523
+msgid "Protocol error"
+msgstr "Ошибка протокола"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1548
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp пользователя %s на %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1551
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp на %s"
+
+#: ../daemon/gvfsbackendsftp.c:1577
+msgid "Unable to find supported ssh command"
+msgstr "Не удаётся найти поддерживаемую команду ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1995
+msgid "Failure"
+msgstr "Ошибка"
+
+#: ../daemon/gvfsbackendsftp.c:2051 ../daemon/gvfsbackendsftp.c:2130
+#: ../daemon/gvfsbackendsftp.c:2141 ../daemon/gvfsbackendsftp.c:2197
+#: ../daemon/gvfsbackendsftp.c:2283 ../daemon/gvfsbackendsftp.c:2333
+#: ../daemon/gvfsbackendsftp.c:2379 ../daemon/gvfsbackendsftp.c:2454
+#: ../daemon/gvfsbackendsftp.c:2561 ../daemon/gvfsbackendsftp.c:2601
+#: ../daemon/gvfsbackendsftp.c:2651 ../daemon/gvfsbackendsftp.c:2723
+#: ../daemon/gvfsbackendsftp.c:2735 ../daemon/gvfsbackendsftp.c:2793
+#: ../daemon/gvfsbackendsftp.c:2835 ../daemon/gvfsbackendsftp.c:3012
+#: ../daemon/gvfsbackendsftp.c:3037 ../daemon/gvfsbackendsftp.c:3092
+#: ../daemon/gvfsbackendsftp.c:3149 ../daemon/gvfsbackendsftp.c:3420
+#: ../daemon/gvfsbackendsftp.c:3487 ../daemon/gvfsbackendsftp.c:3622
+#: ../daemon/gvfsbackendsftp.c:3682 ../daemon/gvfsbackendsftp.c:3717
+#: ../daemon/gvfsbackendsftp.c:3745 ../daemon/gvfsbackendsftp.c:3853
+#: ../daemon/gvfsbackendsftp.c:3907 ../daemon/gvfsbackendsftp.c:3943
+#: ../daemon/gvfsbackendsftp.c:3977 ../daemon/gvfsbackendsftp.c:3992
+#: ../daemon/gvfsbackendsftp.c:4007 ../daemon/gvfsbackendsftp.c:4085
+msgid "Invalid reply received"
+msgstr "Получен неверный ответ"
+
+#: ../daemon/gvfsbackendsftp.c:2103
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Некорректный icon_id «%s» в OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2399
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Ошибка создания резервной копии файла: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2897
+msgid "Unable to create temporary file"
+msgstr "Не удаётся создать временный файл"
+
+#: ../daemon/gvfsbackendsftp.c:3779 ../daemon/gvfsbackendsmb.c:1963
+msgid "Can't move directory over directory"
+msgstr "Не удаётся переместить каталог поверх каталога"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:229
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Требуется пароль для ресурса %s на %s"
+
+#: ../daemon/gvfsbackendsmb.c:485 ../daemon/gvfsbackendsmb.c:531
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Внутренняя ошибка (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:611
+msgid "Failed to mount Windows share"
+msgstr "Ошибка подключения ресурса Windows"
+
+#: ../daemon/gvfsbackendsmb.c:760 ../daemon/gvfsbackendsmb.c:1243
+msgid "Unsupported seek type"
+msgstr "Неподдерживаемый тип поиска"
+
+#: ../daemon/gvfsbackendsmb.c:1335
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Ошибка создания резервного файла: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1865
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Ошибка удаления файла: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1939
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Ошибка перемещения файла: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2011
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Ошибка удаления файла назначения: %s"
+
+#: ../daemon/gvfsbackendsmb.c:2035
+msgid "Can't recursively move directory"
+msgstr "Не удаётся переместить каталог рекурсивно"
+
+#: ../daemon/gvfsbackendsmb.c:2101
+msgid "Windows Shares Filesystem Service"
+msgstr "Служба файловой системы ресурсов Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Требуется пароль для ресурса %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Ресурсы Windows на %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Не удалось получить список доступных на сервере ресурсов"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Этот файл не является монтируемым"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Не является обычным файлом"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Служба сетевой файловой системы Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Папка корзины не может быть удалена"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Элементы в корзине не могут быть изменены"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Корзина"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Неверный тип драйвера"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Ошибка передачи fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Символические ссылки не поддерживаются драйвером"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Неверное сообщение dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Заменить старый демон."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Не запускать fuse"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Демон GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Основной демон GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:140
+#: ../programs/gvfs-open.c:153 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+"Для получения дополнительной информации используйте команду \"%s --help\""
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Неверные аргументы от порождённого дочернего процесса"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Сбой автомонтирования: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Указанный адрес не смонтирован"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Указанный адрес не поддерживается"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Адрес уже смонтирован"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Адрес не является монтируемым"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Диск CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Чистый диск CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Диск CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Чистый диск CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Диск CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Чистый диск CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Диск DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Чистый диск DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Диск DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Чистый диск DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Диск DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Чистый диск DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Диск DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Чистый диск DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Диск DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Чистый диск DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Диск DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Чистый диск DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Диск Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Чистый диск Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Диск Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Чистый диск Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Диск Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Чистый диск Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Диск HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Чистый диск HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Диск HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Чистый диск HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Диск HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Чистый диск HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "МО диск"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Чистый МО диск"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Диск"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Чистый диск"
+
+#: ../monitor/hal/ghaldrive.c:127
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:129
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:131
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:135
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:137
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:139
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:141
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:143
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:145
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:153
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:155
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:157
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:159
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:161
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:163
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:169
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Устройство %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:175
+#, c-format
+msgid "%s Drive"
+msgstr "Устройство %s"
+
+#: ../monitor/hal/ghaldrive.c:179
+msgid "Floppy Drive"
+msgstr "Флоппи-дисковод"
+
+#: ../monitor/hal/ghaldrive.c:185
+msgid "Software RAID Drive"
+msgstr "Устройство программного RAID"
+
+#: ../monitor/hal/ghaldrive.c:187
+msgid "USB Drive"
+msgstr "Устройство USB"
+
+#: ../monitor/hal/ghaldrive.c:189
+msgid "ATA Drive"
+msgstr "Устройство ATA"
+
+#: ../monitor/hal/ghaldrive.c:191
+msgid "SCSI Drive"
+msgstr "Устройство SCSI"
+
+#: ../monitor/hal/ghaldrive.c:193
+msgid "FireWire Drive"
+msgstr "Устройство FireWire"
+
+#: ../monitor/hal/ghaldrive.c:197
+msgid "Tape Drive"
+msgstr "Ленточный накопитель"
+
+#: ../monitor/hal/ghaldrive.c:199
+msgid "CompactFlash Drive"
+msgstr "Устройство CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:201
+msgid "MemoryStick Drive"
+msgstr "Устройство MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:203
+msgid "SmartMedia Drive"
+msgstr "Устройство SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:205
+msgid "SD/MMC Drive"
+msgstr "Устройство SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:207
+msgid "Zip Drive"
+msgstr "Дисковод Zip"
+
+#: ../monitor/hal/ghaldrive.c:209
+msgid "Jaz Drive"
+msgstr "Дисковод Jaz"
+
+#: ../monitor/hal/ghaldrive.c:211
+msgid "Thumb Drive"
+msgstr "USB Flash брелок"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Mass Storage Drive"
+msgstr "Запоминающее устройство"
+
+#: ../monitor/hal/ghaldrive.c:662
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Не удаётся извлечь диск, потому что один или несколько томов этого диска "
+"заняты."
+
+#: ../monitor/hal/ghalmount.c:159 ../monitor/hal/ghalvolume.c:163
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f КБ"
+
+#: ../monitor/hal/ghalmount.c:164 ../monitor/hal/ghalvolume.c:168
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f МБ"
+
+#: ../monitor/hal/ghalmount.c:169 ../monitor/hal/ghalvolume.c:173
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f ГБ"
+
+#: ../monitor/hal/ghalmount.c:323 ../monitor/hal/ghalvolume.c:244
+msgid "Mixed Audio/Data Disc"
+msgstr "Смешанный диск звук/данные"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:336 ../monitor/hal/ghalvolume.c:255
+#, c-format
+msgid "%s Media"
+msgstr "Диск %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:232
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Зашифрованные данные %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: ошибка открытия файла: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, ошибка записи на стандартный вывод"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s, ошибка чтения: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:ошибка закрытия: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "АДРЕС... - каскадировать АДРЕСА на стандартный вывод."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Объединить все файлы в каталоге и вывести их на стандартный вывод. Работает "
+"как стандартная утилита cat, но вместо адреса локального файла использует "
+"адрес gvfs. Например, вы можете использовать адрес вида smb://server/"
+"resource/file.txt"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Примечание: если вам необходимы параметры форматирования, такие как -n, -T "
+"или другие, достаточно просто пропустить вывод через команду cat."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:151
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: не указаны адреса"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:65
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: ошибка открытия адреса: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:92
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: ошибка запуска приложения: %s\n"
+
+#: ../programs/gvfs-open.c:122
+msgid "FILES... - open FILES with registered application."
+msgstr "ФАЙЛЫ... - открывает ФАЙЛЫ в зарегистрированном приложении."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:126
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Открывает файл(ы) в приложении по умолчанию, зарегистрированном для "
+"обработки файлов этого типа."
+
+#~ msgid "The query info operation is not supported"
+#~ msgstr "Операция запроса информации не поддерживается"
+
+#~ msgid "Query info not supported on stream"
+#~ msgstr "Запрос информации не поддерживается потоком"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (в корзине)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Не удаётся удалить корзину"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Уведомление не поддерживается для каталога корзины"
+
+#~ msgid "File unavailable"
+#~ msgstr "Файл недоступен"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Диск %.1f КБ"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Диск %.1f МБ"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Диск %.1f ГБ"
diff --git a/trunk/po/sk.po b/trunk/po/sk.po
new file mode 100644
index 00000000..a1ae4a3a
--- /dev/null
+++ b/trunk/po/sk.po
@@ -0,0 +1,2418 @@
+# translation of gvfs.HEAD.po to Slovak
+# gvfs sk.po
+# Copyright (C) 2000-2001,2003, 2004, 2008 Free Software Foundation, Inc.
+# Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>, 2000-2001,2003, 2004.
+# Ivan Noris, <vix@vazka.sk>, 2004
+# Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>, 2004.
+# Ivan Noris, <vix@vazka.sk>, 2005
+# Marcel Telka, <marcel@telka.sk>, 2008
+# Pavol Šimo, <palo.simo@gmail.com>, 2008
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-10-17 01:00+0200\n"
+"PO-Revision-Date: 2008-09-18 16:17+0200\n"
+"Last-Translator: Pavol Šimo <palo.simo@gmail.com>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural= (n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operácia nie je podporovaná, súbory sú na rôznych bodoch pripojenia"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Neplatná návratová hodnota z get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Neplatná návratová hodnota z query_info"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "Nedá sa získať popisovač súboru prúdu"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+msgid "Invalid return value from open"
+msgstr "Neplatná návratová hodnota z open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+msgid "Didn't get stream file descriptor"
+msgstr "Popisovač súboru prúdu neziskaný"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Neplatná návratová hodnota z call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Neplatná návratová hodnota z get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Nepodarilo sa nájsť súvisiaci objekt pripojenia"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Neplatný názov súboru %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Neplatná návratová hodnota z query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Neplatná návratová hodnota z monotor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Neplatná návratová hodnota z monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:455
+#: ../client/gdaemonfileinputstream.c:464
+#: ../client/gdaemonfileinputstream.c:1306
+#: ../client/gdaemonfileinputstream.c:1316
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Chyba v protokole prúdu: %s"
+
+#: ../client/gdaemonfileinputstream.c:464
+#: ../client/gdaemonfileinputstream.c:1316
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Koniec prúdu"
+
+#: ../client/gdaemonfileinputstream.c:524
+#: ../client/gdaemonfileinputstream.c:680
+#: ../client/gdaemonfileinputstream.c:788
+#: ../client/gdaemonfileinputstream.c:1038
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:734
+#: ../daemon/gvfsbackendobexftp.c:755 ../daemon/gvfsbackendobexftp.c:874
+#: ../daemon/gvfsbackendobexftp.c:1011 ../daemon/gvfsbackendobexftp.c:1075
+#: ../daemon/gvfsbackendobexftp.c:1212 ../daemon/gvfsbackendobexftp.c:1239
+#: ../daemon/gvfsbackendobexftp.c:1298 ../daemon/gvfsbackendobexftp.c:1320
+#: ../daemon/gvfsbackendobexftp.c:1380 ../daemon/gvfsbackendobexftp.c:1399
+#: ../daemon/gvfsbackendsmb.c:1087 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operácia bola zrušená"
+
+#: ../client/gdaemonfileinputstream.c:1213
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Vyhľadanie v prúde nepodporované"
+
+#: ../client/gdaemonfileinputstream.c:1243
+msgid "The query info operation is not supported"
+msgstr "Operácia získania informácií nie je podporovaná"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Vyhľadávacie info v prúde nepodporované"
+
+#: ../client/gdaemonvfs.c:828
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Chyba pri získavaní informácií o pripojení: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Chyba pripojenia k démonu: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Chyba vytvorenia soketu: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Chyba pripojenia k soketu: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Neplatný formát súborových informácií"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "Neplatný obsah zoznamu informácií atribútov"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Chyba pripojenia k D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Služba systému súborov %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Chyba: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Použitie: %s --spawner dbus-id cesta_objektu"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Použitie: %s kľúč=hodnota kľúč=hodnota ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Neurčený typ pripojenia"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "bod pripojenia pre %s už je používaný"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "chyba spustenia démona pripojenia"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ na %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1491
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Neurčený názov hostiteľa"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:554 ../daemon/gvfsbackendobexftp.c:565
+#: ../daemon/gvfsbackendsmb.c:623
+msgid "Invalid mount spec"
+msgstr "Neplatné parametre pripojenia"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2113 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "Súbor neexistuje"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "Súbor nie je priečinkom"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Napaľovanie"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Nie je možné vytvoriť dočasný priečinok"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1094
+#: ../daemon/gvfsbackendgphoto2.c:1983 ../daemon/gvfsbackendgphoto2.c:2702
+#, c-format
+msgid "No such file or directory"
+msgstr "Súbor alebo priečinok neexistuje"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "Priečinok nie je prázdny"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "Nedá sa skopírovať súbor cez priečinok"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Vytváranie CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2776
+msgid "File exists"
+msgstr "Súbor existuje"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobpull.c:173 ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135 ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149 ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119 ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150 ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122 ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operácia nie je backendom podporovaná"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Súbor alebo priečinok v cieľovej ceste neexistuje"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "Nedá sa skopírovať priečinok cez priečinok"
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "Cieľový súbor existuje"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "Nedá sa rekurzívne skopírovať priečinok"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendgphoto2.c:2356
+#: ../daemon/gvfsbackendgphoto2.c:2565 ../daemon/gvfsbackendgphoto2.c:2662
+#: ../daemon/gvfsbackendgphoto2.c:2755
+msgid "Not supported"
+msgstr "Nepodporované"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1399
+msgid "Cannot connect to the system bus"
+msgstr "Nepodarilo sa pripojiť k systémovej zbernici"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1411
+msgid "Cannot create libhal context"
+msgstr "Nepodarilo sa vytvoriť kontext libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1424
+msgid "Cannot initialize libhal"
+msgstr "Nepodarilo sa inicializovať libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Mechanika neurčená"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Mechaniku %s sa nepodarilo nájsť"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Mechanika %s neobsahuje zvukové súbory"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "pripojenie cdda na %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Zvukový disk"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1652
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Súborový systém je zaneprázdnený: %d otvorených súborov"
+msgstr[1] "Súborový systém je zaneprázdnený: %d otvorený súbor"
+msgstr[2] "Súborový systém je zaneprázdnený: %d otvorené súbory"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Súbor %s na zariadení %s neexistuje"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Chyba knižnice 'paranoia' na zariadení %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Chyba vyhľadania v prúde na zariadení %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1709
+#, c-format
+msgid "No such file"
+msgstr "Súbor neexistuje"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Súbor neexistuje alebo nie je zvukovou stopou"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Služba systému súborov Zvukové CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Počítač"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Systém súborov"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1701
+#: ../daemon/gvfsbackendobexftp.c:720 ../daemon/gvfsbackendsmb.c:666
+#: ../daemon/gvfsbackendtrash.c:678 ../daemon/gvfsbackendtrash.c:1786
+msgid "Can't open directory"
+msgstr "Priečinok sa nedá otvoriť"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "Pripojiteľný súbor sa nedá otvoriť"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Interná chyba: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "Súbor sa nedá pripojiť"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "Žiaden disk v mechanike"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Nie je pripojiteľný súbor"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "Súbor sa nedá odpojiť"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "Súbor sa nedá vysunúť"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Chyba HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "Nepodarilo sa spracovať odpoveď"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Prázdna odpoveď"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Neočakávaná odpoveď zo servra"
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr "Neplatná odpoveď"
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr "Zdieľanie WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr "Zadajte heslo pre %s"
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr "Prosím zadajte heslo pre proxy"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr "Nie je zdieľanie WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "Zdieľanie WebDAV na %s"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr "Nepodarilo sa vytvoriť požiadavku"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1711
+#: ../daemon/gvfsbackendftp.c:2377 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1822
+msgid "Target file already exists"
+msgstr "Cieľový súbor už existuje"
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1056
+msgid "The file was externally modified"
+msgstr "Súbor bol zmenený zvonka"
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1092
+#: ../daemon/gvfsbackendsmb.c:1839
+msgid "Backup file creation failed"
+msgstr "Vytvorenie záložného súboru zlyhalo"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Súbor alebo adresár sa nedá sledovať"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Sieť"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "Účty nie sú podporované"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "Hostiteľ uzavrel spojenie"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Nepodarilo sa otvoriť dátové spojenie. Nezabraňuje tomu firewall?"
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "Dátové spojenie uzavreté"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Operácia zlyhala"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "Na servri už nie je miesto"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Operácia nepodporovaná"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Prístup odmietnutý"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "Neznámy typ stránky"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2223
+msgid "Invalid filename"
+msgstr "Neplatný názov súboru"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Neplatná odpoveď"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "prenos prerušovaný"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "Pripojenie k hostiteľovi sa nepodarilo"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1345
+#, fuzzy, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Zadajte heslo pre ftp na %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1348
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Zadajte heslo pre ftp na %s"
+
+#: ../daemon/gvfsbackendftp.c:1374 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Dialógové okno zadania hesla bolo zrušené"
+
+#: ../daemon/gvfsbackendftp.c:1453
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp na %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1457
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp ako %s na %s"
+
+#: ../daemon/gvfsbackendftp.c:1541 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "Súbor je priečinkom"
+
+#: ../daemon/gvfsbackendftp.c:1763 ../daemon/gvfsbackendftp.c:2338
+msgid "backups not supported yet"
+msgstr "zálohy momentálne nie sú podporované"
+
+#: ../daemon/gvfsbackendftp.c:1840
+msgid "filename too long"
+msgstr "príliš dlhý názov súboru"
+
+#: ../daemon/gvfsbackendftp.c:2357
+msgid "Invalid destination filename"
+msgstr "Neplatný názov súboru cieľa"
+
+#: ../daemon/gvfsbackendgphoto2.c:497
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Súbor alebo priečinok existuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:504
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Súbor alebo priečinok neexistuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:510
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Neplatný názov súboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:516
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Nepodporované"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:689
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitálny fotoaparát (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Digitálny fotoaparát %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:840 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Prehrávač hudby %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:849 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Digitálny fotoaparát"
+
+#: ../daemon/gvfsbackendgphoto2.c:851 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Prehrávač hudby"
+
+#: ../daemon/gvfsbackendgphoto2.c:1321 ../daemon/gvfsbackendgphoto2.c:2010
+msgid "Failed to get folder list"
+msgstr "Získanie zoznamu priečinkov zlyhalo"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "No device specified"
+msgstr "Zariadenie neurčené"
+
+#: ../daemon/gvfsbackendgphoto2.c:1456
+msgid "Cannot create gphoto2 context"
+msgstr "Nepodarilo sa vytvoriť kontext gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1466
+msgid "Error creating camera"
+msgstr "Chyba vytvorenia fotoaparátu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479 ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error loading device information"
+msgstr "Chyba načítania informácií o zariadení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1501
+msgid "Error looking up device information"
+msgstr "Chyba vyhľadania informácií o zariadení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1511
+msgid "Error getting device information"
+msgstr "Chyba získania informácií o zariadení"
+
+#: ../daemon/gvfsbackendgphoto2.c:1524
+msgid "Error setting up camera communications port"
+msgstr "Chyba nastavenia komunikačného portu s fotoaparátom"
+
+#: ../daemon/gvfsbackendgphoto2.c:1535
+msgid "Error initializing camera"
+msgstr "Chyba inicializácie fotoaparátu"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1549
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "pripojenie gphoto2 na %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1624
+msgid "No camera specified"
+msgstr "Neurčený žiaden fotoaparát"
+
+#: ../daemon/gvfsbackendgphoto2.c:1717
+msgid "Error creating file object"
+msgstr "Chyba pri vytváraní súborového objektu"
+
+#: ../daemon/gvfsbackendgphoto2.c:1732
+msgid "Error getting file"
+msgstr "Chyba pri získavaní súboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:1742
+msgid "Error getting data from file"
+msgstr "Chyba pri získavaní údajov zo súboru"
+
+# c-format
+#: ../daemon/gvfsbackendgphoto2.c:1837 ../daemon/gvfsbackendgphoto2.c:3026
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Chyba vyhľadania v prúde na fotoaparáte %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1977 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Nie je priečinkom"
+
+#: ../daemon/gvfsbackendgphoto2.c:2076
+msgid "Failed to get file list"
+msgstr "Získanie zoznamu súborov zlyhalo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2368
+msgid "Error creating directory"
+msgstr "Chyba vytvorenia priečinka"
+
+#: ../daemon/gvfsbackendgphoto2.c:2577
+msgid "Name already exists"
+msgstr "Názov už existuje"
+
+#: ../daemon/gvfsbackendgphoto2.c:2588 ../daemon/gvfsbackendgphoto2.c:3217
+msgid "New name too long"
+msgstr "Nový názov je príliš dlhý"
+
+#: ../daemon/gvfsbackendgphoto2.c:2598 ../daemon/gvfsbackendgphoto2.c:3228
+msgid "Error renaming dir"
+msgstr "Chyba premenovania priečinka"
+
+#: ../daemon/gvfsbackendgphoto2.c:2611 ../daemon/gvfsbackendgphoto2.c:3241
+msgid "Error renaming file"
+msgstr "Chyba prremenovania súboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:2675
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Priečinok '%s' nie je prázdny"
+
+#: ../daemon/gvfsbackendgphoto2.c:2686
+msgid "Error deleting directory"
+msgstr "Chyba pri odstraňovaní priečinka"
+
+#: ../daemon/gvfsbackendgphoto2.c:2712
+msgid "Error deleting file"
+msgstr "Chyba pri odstraňovaní súboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:2765
+msgid "Can't write to directory"
+msgstr "Do priečinka sa nedá zapisovať"
+
+#: ../daemon/gvfsbackendgphoto2.c:2812
+msgid "Cannot allocate new file to append to"
+msgstr "Nepodarilo sa alokovať súbor na dopisovanie"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot read file to append to"
+msgstr "Nepodarilo sa čítať súbor na dopisovanie"
+
+#: ../daemon/gvfsbackendgphoto2.c:2838
+msgid "Cannot get data of file to append to"
+msgstr "Nepodarilo sa získať údaje zo súboru na dopisovanie"
+
+#: ../daemon/gvfsbackendgphoto2.c:3125
+msgid "Error writing file"
+msgstr "Chyba pri zápise do súboru"
+
+#: ../daemon/gvfsbackendgphoto2.c:3173
+msgid "Not supported (not same directory)"
+msgstr "Nie je podporované (nie je ten istý priečinok)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3185
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Nie je podporované (zdroj aj cieľ je priečinok)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3193
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Nie je podporované (zdroj je priečinok, cieľ existujúci súbor)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3205
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Nie je podporované (zdroj je súbor, cieľ priečinok)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Chyba klienta HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1319 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (neplatný Unicode kód)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Upozorňovanie nie je podporované pre priečinky"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Sieť Windows"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Lokálna sieť"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Sledovanie sieťových umiestnení"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:380 ../daemon/gvfsbackendsmb.c:528
+#: ../daemon/gvfsbackendsmb.c:1312
+#, c-format
+msgid "%s on %s"
+msgstr "%s na %s"
+
+#: ../daemon/gvfsbackendobexftp.c:659
+msgid "Connection to the device lost"
+msgstr "Spojenie so zariadením stratené"
+
+#: ../daemon/gvfsbackendobexftp.c:1156
+msgid "Device requires a software update"
+msgstr "Zariadenie vyžaduje aktualizáciu softvéru"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "Program ssh neočakávane skončil"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Neznámy názov hostiteľa"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Cesta k počítaču neexistuje"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "Pripojenie odmietnuté serverom"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Overenie kľúča hostiteľa zlyhalo"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "Nepodarilo sa spustiť program ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Nepodarilo sa spustiť program ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Časový limit prihlásenia vypršal"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Zadajte heslovú frázu pre kľúč"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Zadajte heslo"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "Nepodarilo sa odoslať heslo"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Aj tak sa prihlásiť"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Zrušiť prihlásenie"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Totožnosť vzdialeného počítača (%s) nie je známa.\n"
+"To sa stane pri prvom prihlásení k počítaču.\n"
+"\n"
+"Totožnosť odoslaná vzdialeným počítačom je %s. Ak chcete mať absolútnu "
+"istotu, že je bezpečné pokračovať, kontaktujte svojho správcu systému."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Dialógové okno prihlásenia bolo zrušené"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "Nepodarilo sa odoslať potvrdenie identity hostiteľa"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Chyba protokolu"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp na %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "Nepodarilo sa nájsť podporovaný príkaz ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Zlyhanie"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "Prijatá neplatná odpoveď"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Chyba pri vytváraní záložného súboru: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "Nepodarilo sa vytvoriť dočasný súbor"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1811
+msgid "Can't move directory over directory"
+msgstr "Nedá sa presunúť priečinok cez priečinok"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:213
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Pre sieťový disk %s na %s je vyžadované heslo"
+
+#: ../daemon/gvfsbackendsmb.c:468 ../daemon/gvfsbackendsmb.c:514
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Interná chyba (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:587
+msgid "Failed to mount Windows share"
+msgstr "Nepodarilo sa pripojiť sieťový disk Windows"
+
+#: ../daemon/gvfsbackendsmb.c:735 ../daemon/gvfsbackendsmb.c:1191
+msgid "Unsupported seek type"
+msgstr "Nepodporovaný typ vyhľadania"
+
+#: ../daemon/gvfsbackendsmb.c:1255
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Vytvorenie záložného súboru zlyhalo: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1713
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Chyba pri odstraňovaní súboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1787
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Chyba pri presúvaní súboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1859
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Chyba pri odstraňovaní cieľového súboru: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1883
+msgid "Can't recursively move directory"
+msgstr "Nedá sa rekurzívne premiestniť priečinok"
+
+#: ../daemon/gvfsbackendsmb.c:1946
+msgid "Windows Shares Filesystem Service"
+msgstr "Služba systému súborov Sieťové disky Windows"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Sieťové disky Windows na %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "Súbor nie je pripojiteľný"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Nie je obyčajným súborom"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Služba súborového systému Sieť Windows"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Kôš"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (v koši)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "Kôš sa nedá odstrániť"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Oznamovanie zmien priečinka Kôš nie je podporované"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Neplatný typ backendu"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Chyba pri odoslaní fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Mäkké odkazy nie sú backendom podporované"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Neplatná správa D-Bus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Nahradiť starý démon"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Neštartovať FUSE"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Démon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Hlavný démon pre GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Pre viac informácií skúste \"%s --help\""
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Neplatné parametre od vyvolaného potomka"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount zlyhal: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Uvedené umiestnenie nie je pripojené"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Uvedené umiestnenie nie je podporované"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Umiestnenie už je pripojené"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Umiestnenie nie je pripojiteľné"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Mechanika %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Mechanika %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disketová mechanika"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Softvérový RAID disk"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB mechanika"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA mechanika"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI mechanika"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire mechanika"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Pásková mechanika"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Mechanika CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Mechanika MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Mechanika SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Mechanika SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Mechanika Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Mechanika Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Palcová mechanika"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Mechanika hromadného ukladania údajov"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Vysunutie média zlyhalo; jeden alebo viac zväzkov média je zaneprázdnených"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f KB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Zmiešaný zvukový/dátový disk"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s médium"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s šifrovaných údajov"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disk CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Čistý disk CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disk CD-R"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Čistý disk CD-R"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disk CD-RW"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Čistý disk CD-RW"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disk DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Čistý disk DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disk DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Čistý disk DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disk DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Čistý disk DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disk DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Čistý disk DVD+R"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disk DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Čistý disk DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disk DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Čistý disk DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disk Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Čistý disk Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disk Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Čistý disk Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disk Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Čistý disk Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disk HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Čistý disk HD DVD"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disk HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Čistý disk HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disk HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Čistý disk HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disk MO"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Čistý disk MO"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Čistý disk"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s - %s: chyba pri otváraní súboru: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s - %s, chyba zápisu do štandardného výstupu"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s - %s: chyba pri čítaní: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s - %s: chyba pri zatváraní: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "UMIESTNENIE... - spojiť UMIESTNENIA do štandardného výstupu"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Spojí súbory na zadaných umiestneniach a vypíše ich na štandardný výstup. "
+"Presne ako tradičný nástroj cat, ale používa gvfs umiestnenia namisto "
+"lokálnych súborov: napríklad ako umiestnenie môžete použiť niečo ako smb://"
+"server/zdroj/súbor.txt."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Poznámka: jednoducho prežente cez cat, ak potrebujete jeho formátovacie "
+"voľby ako -n, -T alebo iné."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: nezadané umiestnenie"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s - %s: chyba pri otváraní umiestnenia: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s - %s: chyba pri spúšťaní aplikácie: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "SÚBORY... - otvoriť SÚBORY zaregistrovanou aplikáciou"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Otvorí súbor (súbory) predvolenou aplikáciou zaregistrovanou na obsluhu "
+"zvoleného typu súboru."
+
+#~ msgid "File unavailable"
+#~ msgstr "Súbor nie je k dispozícii"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f KB médium"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB médium"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB médium"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Zvukový disk"
+
+#~ msgid "The file does not exist"
+#~ msgstr "Taký súbor neexistuje"
+
+#~ msgid "ISO 9660 Volume"
+#~ msgstr "Zväzok ISO 9660"
+
+#~ msgid "%s:%u contains NUL characters."
+#~ msgstr "%s:%u obsahuje znaky NUL."
+
+#~ msgid "%s:%u contains no method name."
+#~ msgstr "%s:%u neobsahuje názov metódy."
+
+#~ msgid "%s:%u has no options endmarker."
+#~ msgstr "%s:%u neobsahuje koncovú značku volieb."
+
+#~ msgid "%s:%u has unknown options %s."
+#~ msgstr "%s:%u obsahuje neznáme voľby %s."
+
+#~ msgid "%s:%u contains no module name."
+#~ msgstr "%s:%u neobsahuje názov modulu."
+
+#~ msgid "Configuration file `%s' was not found: %s"
+#~ msgstr "Konfiguračný súbor '%s' nebol nájdený: %s"
+
+#~ msgid "AFFS Volume"
+#~ msgstr "Zväzok AFFS"
+
+#~ msgid "AFS Network Volume"
+#~ msgstr "Sieťový zväzok AFS"
+
+#~ msgid "Auto-detected Volume"
+#~ msgstr "Automaticky určený zväzok"
+
+#~ msgid "CD-ROM Drive"
+#~ msgstr "Mechanika CD-ROM"
+
+#~ msgid "CD Digital Audio"
+#~ msgstr "Zvukové CD"
+
+#~ msgid "Hardware Device Volume"
+#~ msgstr "Zväzok hardvérového zariadenia"
+
+#~ msgid "EncFS Volume"
+#~ msgstr "Zväzok EncFS"
+
+#~ msgid "Ext2 Linux Volume"
+#~ msgstr "Zväzok Ext2 Linux"
+
+#~ msgid "Ext3 Linux Volume"
+#~ msgstr "Zväzok Ext3 Linux"
+
+#~ msgid "MSDOS Volume"
+#~ msgstr "Zväzok MSDOS"
+
+#~ msgid "BSD Volume"
+#~ msgstr "Zväzok BSD"
+
+#~ msgid "FUSE Volume"
+#~ msgstr "Zväzok FUSE"
+
+#~ msgid "MacOS Volume"
+#~ msgstr "Zväzok MacOS"
+
+#~ msgid "CDROM Volume"
+#~ msgstr "Zväzok CDROM"
+
+#~ msgid "Hsfs CDROM Volume"
+#~ msgstr "Zväzok Hsfs CDROM"
+
+#~ msgid "JFS Volume"
+#~ msgstr "Zväzok JFS"
+
+#~ msgid "Windows NT Volume"
+#~ msgstr "Zväzok Windows NT"
+
+#~ msgid "System Volume"
+#~ msgstr "Systémový zväzok"
+
+#~ msgid "Memory Volume"
+#~ msgstr "Pamäťový zväzok"
+
+#~ msgid "Minix Volume"
+#~ msgstr "Zväzok Minix"
+
+#~ msgid "NFS Network Volume"
+#~ msgstr "Sieťový zväzok NFS"
+
+#~ msgid "Netware Volume"
+#~ msgstr "Zväzok Netware"
+
+#~ msgid "Reiser4 Linux Volume"
+#~ msgstr "Linuxový zväzok Reiser4"
+
+#~ msgid "ReiserFS Linux Volume"
+#~ msgstr "Linuxový zväzok ReiserFS"
+
+#~ msgid "SuperMount Volume"
+#~ msgstr "Zväzok SuperMount"
+
+#~ msgid "DVD Volume"
+#~ msgstr "Zväzok DVD"
+
+#~ msgid "Solaris/BSD Volume"
+#~ msgstr "Zväzok Solaris/BSD"
+
+#~ msgid "Udfs Solaris Volume"
+#~ msgstr "Zväzok Solaris Udfs"
+
+#~ msgid "Pcfs Solaris Volume"
+#~ msgstr "Zväzok Solaris Pcfs"
+
+#~ msgid "Sun SAM-QFS Volume"
+#~ msgstr "Zväzok Sun SAM-QFS"
+
+#~ msgid "Temporary Volume"
+#~ msgstr "Dočasný zväzok"
+
+#~ msgid "Enhanced DOS Volume"
+#~ msgstr "Rozšírený zväzok DOS"
+
+#~ msgid "Windows VFAT Volume"
+#~ msgstr "Zväzok Windows VFAT"
+
+#~ msgid "Xenix Volume"
+#~ msgstr "Zväzok Xenix"
+
+#~ msgid "XFS Linux Volume"
+#~ msgstr "Linuxový zväzok XFS"
+
+#~ msgid "XIAFS Volume"
+#~ msgstr "Zväzok XIAFS"
+
+#~ msgid "CIFS Volume"
+#~ msgstr "Zväzok CIFS"
+
+#~ msgid "Unknown"
+#~ msgstr "Neznámy"
+
+#~ msgid "%s Volume"
+#~ msgstr "Zväzok %s"
+
+#~ msgid "Pen Drive"
+#~ msgstr "Mechanika Pen"
+
+#~ msgid "External %s"
+#~ msgstr "Externá %s"
+
+#~ msgid "%s Removable Volume"
+#~ msgstr "Výmenný zväzok %s"
+
+#~ msgid "Volume"
+#~ msgstr "Zväzok"
+
+#~ msgid "Unknown operation type %u"
+#~ msgstr "Neznámy typ operácie %u"
+
+#~ msgid "Cannot create pipe for open GIOChannel: %s"
+#~ msgstr "Nemožno vytvoriť rúru pre otvorenie GIOChannel: %s"
+
+#~ msgid "Unknown job kind %u"
+#~ msgstr "Neznámy druh úlohy %u"
+
+#~ msgid ""
+#~ "Deprecated function. User modifications to the MIME database are no "
+#~ "longer supported."
+#~ msgstr ""
+#~ "Zastaralá funkcia. Používateľské zmeny MIME databázy už nie sú "
+#~ "podporované."
+
+#~ msgid "More parsing errors will be ignored."
+#~ msgstr "Ďalšie chyby analýzy budú ignorované."
+
+#~ msgid "No error"
+#~ msgstr "Bez chyby"
+
+#~ msgid "File not found"
+#~ msgstr "Súbor nenájdený"
+
+#~ msgid "Generic error"
+#~ msgstr "Všeobecná chyba"
+
+#~ msgid "I/O error"
+#~ msgstr "V/V chyba"
+
+#~ msgid "Data corrupted"
+#~ msgstr "Poškodené dáta"
+
+#~ msgid "Format not valid"
+#~ msgstr "Neplatný formát"
+
+#~ msgid "Bad file handle"
+#~ msgstr "Chybný handle súboru"
+
+#~ msgid "File too big"
+#~ msgstr "Príliš veľký súbor"
+
+#~ msgid "Read-only file system"
+#~ msgstr "Súborový systém len pre čítanie"
+
+#~ msgid "Invalid URI"
+#~ msgstr "Neplatné URI"
+
+#~ msgid "File not open"
+#~ msgstr "Neotvorený súbor"
+
+#~ msgid "Open mode not valid"
+#~ msgstr "Mód otvorenia neplatný"
+
+#~ msgid "Too many open files"
+#~ msgstr "Príliš veľa otvorených súborov"
+
+#~ msgid "Operation in progress"
+#~ msgstr "Operácia prebieha"
+
+#~ msgid "Operation interrupted"
+#~ msgstr "Operácia prerušená"
+
+#~ msgid "Looping links encountered"
+#~ msgstr "Vyskytli sa cyklické odkazy"
+
+#~ msgid "Not enough memory"
+#~ msgstr "Nedostatok pamäti"
+
+#~ msgid "Host not found"
+#~ msgstr "Hostiteľ nenájdený"
+
+#~ msgid "Host has no address"
+#~ msgstr "Hostiteľ nemá adresu"
+
+#~ msgid "Login failed"
+#~ msgstr "Zlyhalo prihlásenie"
+
+#~ msgid "Directory busy"
+#~ msgstr "Priečinok zaneprázdnený"
+
+#~ msgid "Too many links"
+#~ msgstr "Príliš veľa odkazov"
+
+#~ msgid "Read only file system"
+#~ msgstr "Súborový systém len pre čítanie"
+
+#~ msgid "Not on the same file system"
+#~ msgstr "Nie je na rovnakom súborovom systéme"
+
+#~ msgid "Request obsoletes service's data"
+#~ msgstr "Požiadavka zneplatňuje dáta služby"
+
+#~ msgid "No default action associated"
+#~ msgstr "Nedefinovaná žiadna štandardná akcia"
+
+#~ msgid "No handler for URL scheme"
+#~ msgstr "Pre URL schému nie je ovládací program"
+
+#~ msgid "Error parsing command line"
+#~ msgstr "Chyba pri analýze príkazového riadku"
+
+#~ msgid "Timeout reached"
+#~ msgstr "Čas vypršal"
+
+#~ msgid "Nameserver error"
+#~ msgstr "Chyba menného servera"
+
+#~ msgid "The resource is locked"
+#~ msgstr "Prostriedok je uzamknutý"
+
+#~ msgid "Function call deprecated"
+#~ msgstr "Volanie funkcie je zastaralá"
+
+#~ msgid "Unknown error"
+#~ msgstr "Neznáma chyba"
+
+#~ msgid "%u byte"
+#~ msgid_plural "%u bytes"
+#~ msgstr[0] "%u bajtov"
+#~ msgstr[1] "%u bajt"
+#~ msgstr[2] "%u bajty"
+
+#~ msgid "Floppy"
+#~ msgstr "Disketa"
+
+#~ msgid "CD-ROM/DVD-ROM"
+#~ msgstr "CD-ROM/DVD-ROM"
+
+#~ msgid "CD-ROM/DVD-RAM"
+#~ msgstr "CD-ROM/DVD-RAM"
+
+#~ msgid "CD-ROM/DVD-R"
+#~ msgstr "CD-ROM/DVD-R"
+
+#~ msgid "CD-ROM/DVD-RW"
+#~ msgstr "CD-ROM/DVD-RW"
+
+#~ msgid "CD-R/DVD-ROM"
+#~ msgstr "CD-R/DVD-ROM"
+
+#~ msgid "CD-R/DVD-RAM"
+#~ msgstr "CD-R/DVD-RAM"
+
+#~ msgid "CD-R/DVD-R"
+#~ msgstr "CD-R/DVD-R"
+
+#~ msgid "CD-R/DVD-RW"
+#~ msgstr "CD-R/DVD-RW"
+
+#~ msgid "CD-RW/DVD-ROM"
+#~ msgstr "CD-RW/DVD-ROM"
+
+#~ msgid "CD-RW/DVD-RAM"
+#~ msgstr "CD-RW/DVD-RAM"
+
+#~ msgid "CD-RW/DVD-R"
+#~ msgstr "CD-RW/DVD-R"
+
+#~ msgid "CD-RW/DVD-RW"
+#~ msgstr "CD-RW/DVD-RW"
+
+#~ msgid "IEEE1394 Drive"
+#~ msgstr "Mechanika IEEE1394"
+
+#~ msgid "CF"
+#~ msgstr "CF"
+
+#~ msgid "SD/MMC"
+#~ msgstr "SD/MMC"
+
+#~ msgid "Memory Stick"
+#~ msgstr "Memory Stick"
+
+#~ msgid "Root Volume"
+#~ msgstr "Koreňový zväzok"
+
+#~ msgid "Audio CD"
+#~ msgstr "Zvukové CD"
+
+#~ msgid "Unknown volume"
+#~ msgstr "Neznámy zväzok"
+
+#~ msgid "Network server"
+#~ msgstr "Sieťový server"
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. There is probably no floppy in the "
+#~ "drive."
+#~ msgstr "Nepodarilo sa pripojiť disketu. Možno v mechanike žiadna nie je."
+
+#~ msgid ""
+#~ "Unable to mount the volume. There is probably no media in the device."
+#~ msgstr "Nepodarilo sa pripojiť zväzok. Možno v mechanike nie je médium."
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. The floppy is probably in a format that "
+#~ "cannot be mounted."
+#~ msgstr ""
+#~ "Nepodarilo sa pripojiť disketu. Disketa asi nie je v podporovanom formáte."
+
+#~ msgid ""
+#~ "Unable to mount the selected volume. The volume is probably in a format "
+#~ "that cannot be mounted."
+#~ msgstr ""
+#~ "Nepodarilo sa pripojiť zadaný zväzok. Zväzok asi nie je v podporovanom "
+#~ "formáte."
+
+#~ msgid "Unable to mount the selected floppy drive."
+#~ msgstr "Nepodarilo sa pripojiť zadanú disketu."
+
+#~ msgid "Unable to mount the selected volume."
+#~ msgstr "Nepodarilo sa pripojiť zadaný disk."
+
+#~ msgid ""
+#~ "Unable to unmount the selected volume. The volume is in use by one or "
+#~ "more programs."
+#~ msgstr ""
+#~ "Nepodarilo sa odpojiť zadaný zväzok. Zväzok je používaný jedným alebo "
+#~ "viacerými programami."
+
+#~ msgid "Unable to unmount the selected volume."
+#~ msgstr "Nepodarilo sa odpojiť zadaný zväzok."
+
+#~ msgid "Unable to eject media"
+#~ msgstr "Nepodarilo sa vysunúť médium"
+
+#~ msgid "Home"
+#~ msgstr "Domovský priečinok"
+
+#~ msgid "Unknown GnomeVFSSeekPosition %d"
+#~ msgstr "Neznáma GnomeVFSSeekPosition %d"
+
+#~ msgid "The identity of the remote computer (%s) is unknown."
+#~ msgstr "Totožnosť vzdialeného počítača (%s) je neznáma."
+
+#~ msgid "Didn't find a valid settings file at %s\n"
+#~ msgstr "Nepodarilo sa nájsť platný súbor s nastavením v %s\n"
+
+#~ msgid "Use the %s environment variable to specify a different location.\n"
+#~ msgstr "Pre zadanie iného umiestnenia použite premennú prostredia %s.\n"
+
+#~ msgid "Default component viewer application"
+#~ msgstr "Štandardná aplikácia prehliadača súčastí"
+
+#~ msgid "Default terminal application"
+#~ msgstr "Štandardná aplikácia terminálu"
+
+#~ msgid "Exec argument for default terminal"
+#~ msgstr "Argument spustenia pre štandardný terminál"
+
+#~ msgid ""
+#~ "The application to use for viewing files that require a component to view "
+#~ "them. The parameter %s will be replaced by the file's URIs, the parameter "
+#~ "%c will be replaced by the component IID."
+#~ msgstr ""
+#~ "Aplikácia používaná pre zobrazenie súborov, ktoré vyžadujú nejakú súčasť "
+#~ "pre zobrazenie. Parameter %s bude nahradený URI súborov, parameter %c "
+#~ "bude nahradený IID súčasti."
+
+#~ msgid ""
+#~ "The default terminal application to use for applications that require a "
+#~ "terminal."
+#~ msgstr ""
+#~ "Štandardná aplikácia terminálu používaná pre aplikácie, ktoré vyžadujú "
+#~ "terminál."
+
+#~ msgid "The exec argument to use for the default terminal application."
+#~ msgstr "Parameter používaný pri spúšťaní štandardnej aplikácie terminálu."
+
+#~ msgid "Run the command in a terminal"
+#~ msgstr "Spustiť program v termináli"
+
+#~ msgid "The command used to handle \"aim\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"aim\", ak je povolené."
+
+#~ msgid "The command used to handle \"callto\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"callto\", ak je povolené."
+
+#~ msgid "The command used to handle \"ghelp\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"ghelp\", ak je povolené."
+
+#~ msgid "The command used to handle \"h323\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"h323\", ak je povolené."
+
+#~ msgid "The command used to handle \"http\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"http\", ak je povolené."
+
+#~ msgid "The command used to handle \"https\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"https\", ak je povolené."
+
+#~ msgid "The command used to handle \"info\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"info\", ak je povolené."
+
+#~ msgid "The command used to handle \"mailto\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"mailto\", ak je povolené."
+
+#~ msgid "The command used to handle \"man\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"man\", ak je povolené."
+
+#~ msgid "The command used to handle \"trash\" URLs, if enabled."
+#~ msgstr "Príkaz použitý na obsluhovanie URL \"trash\", ak je povolené."
+
+#~ msgid "The handler for \"aim\" URLs"
+#~ msgstr "Obslužný program pre URL \"aim\""
+
+#~ msgid "The handler for \"callto\" URLs"
+#~ msgstr "Obslužný program pre URL \"callto\""
+
+#~ msgid "The handler for \"ghelp\" URLs"
+#~ msgstr "Obslužný program pre URL \"ghelp\""
+
+#~ msgid "The handler for \"h323\" URLs"
+#~ msgstr "Obslužný program pre URL \"h323\""
+
+#~ msgid "The handler for \"http\" URLs"
+#~ msgstr "Obslužný program pre URL \"http\""
+
+#~ msgid "The handler for \"https\" URLs"
+#~ msgstr "Obslužný program pre URL \"https\""
+
+#~ msgid "The handler for \"info\" URLs"
+#~ msgstr "Obslužný program pre URL \"info\""
+
+#~ msgid "The handler for \"mailto\" URLs"
+#~ msgstr "Obslužný program pre URL \"mailto\""
+
+#~ msgid "The handler for \"man\" URLs"
+#~ msgstr "Obslužný program pre URL \"man\""
+
+#~ msgid "The handler for \"trash\" URLs"
+#~ msgstr "Obslužný program pre URL \"trash\""
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"aim"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"aim\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"callto\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"callto"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"ghelp"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"ghelp"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"h323"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"h323"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"http"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"http"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"https"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"https"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"info"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"info"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"mailto\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"mailto"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"man"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"man\"."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"trash"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "True, ak program zadaný v kľúči \"command\" by mal obsluhovať URL \"trash"
+#~ "\"."
+
+#~ msgid ""
+#~ "True if the command used to handle this type of URL should be run in a "
+#~ "terminal."
+#~ msgstr ""
+#~ "True, ak má byť program, použitý na obsluhu tohoto typu URL, spustený v "
+#~ "termináli."
+
+#~ msgid "Whether the specified command should handle \"aim\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"aim\""
+
+#~ msgid "Whether the specified command should handle \"callto\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"callto\""
+
+#~ msgid "Whether the specified command should handle \"ghelp\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"ghelp\""
+
+#~ msgid "Whether the specified command should handle \"h323\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"h323\""
+
+#~ msgid "Whether the specified command should handle \"http\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"http\""
+
+#~ msgid "Whether the specified command should handle \"https\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"https\""
+
+#~ msgid "Whether the specified command should handle \"info\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"info\""
+
+#~ msgid "Whether the specified command should handle \"mailto\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"mailto\""
+
+#~ msgid "Whether the specified command should handle \"man\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"man\""
+
+#~ msgid "Whether the specified command should handle \"trash\" URLs"
+#~ msgstr "Či má zadaný príkaz obsuhovať URL \"trash\""
+
+#~ msgid ""
+#~ "Comma separated list of DNS-SD domains that should be visible in the "
+#~ "\"network:///\" location."
+#~ msgstr ""
+#~ "Čiarkou oddelený zoznam DNS-SD domén, ktoré majú byť viditeľné v "
+#~ "umiestnení \"network:///\"."
+
+#~ msgid "Extra domains to look for DNS-SD services in"
+#~ msgstr "Ďalšie domény, v ktorých sa majú hľadať služby DNS-SD"
+
+#~ msgid "How to display local DNS-SD service"
+#~ msgstr "Ako sa má zobraziť miestna služba DNS-SD"
+
+#~ msgid "Possible values are \"merged\", \"separate\" and \"disabled\"."
+#~ msgstr "Prípustné hodnoty sú \"merged\", \"separate\" a \"disabled\"."
+
+#~ msgid "Authenticate proxy server connections"
+#~ msgstr "Overovať totožnosť spojení s proxy serverom"
+
+#~ msgid "Automatic proxy configuration URL"
+#~ msgstr "URL pre automatické nastavenie proxy"
+
+#~ msgid "Enables the proxy settings when accessing HTTP over the Internet."
+#~ msgstr "Povolí nastavenie proxy pri prístupe pomocou HTTP na Internet."
+
+#~ msgid "FTP proxy host name"
+#~ msgstr "Hostiteľ pre FTP proxy"
+
+#~ msgid "FTP proxy port"
+#~ msgstr "Port pre FTP proxy"
+
+#~ msgid "HTTP proxy host name"
+#~ msgstr "Hostiteľ pre HTTP proxy"
+
+#~ msgid "HTTP proxy port"
+#~ msgstr "Port pre HTTP proxy"
+
+#~ msgid "HTTP proxy username"
+#~ msgstr "Meno používateľa pre HTTP proxy"
+
+#~ msgid ""
+#~ "If true, then connections to the proxy server require authentication. The "
+#~ "username/password combo is defined by \"/system/http_proxy/"
+#~ "authentication_user\" and \"/system/http_proxy/authentication_password\"."
+#~ msgstr ""
+#~ "Ak je true, pripojenia k proxy serveru vyžadujú overenie totožnosti. "
+#~ "Kombinácia používateľ/heslo je definovaná v \"/system/http_proxy/"
+#~ "authentication_user\" a \"/system/http_proxy/authentication_password\"."
+
+#~ msgid "Non-proxy hosts"
+#~ msgstr "Hostitelia bez použitia proxy"
+
+#~ msgid "Password to pass as authentication when doing HTTP proxying."
+#~ msgstr "Heslo používané pre prihlásenie k proxy HTTP."
+
+#~ msgid "Proxy configuration mode"
+#~ msgstr "Režim nastavenia proxy"
+
+#~ msgid "SOCKS proxy host name"
+#~ msgstr "Hostiteľ proxy pre SOCKS"
+
+#~ msgid "SOCKS proxy port"
+#~ msgstr "Port proxy pre SOCKS"
+
+#~ msgid "Secure HTTP proxy host name"
+#~ msgstr "Hostiteľ proxy pre zabezpečené HTTP"
+
+#~ msgid "Secure HTTP proxy port"
+#~ msgstr "Port proxy pre zabezpečené HTTP"
+
+#~ msgid ""
+#~ "Select the proxy configuration mode. Supported values are \"none\", "
+#~ "\"manual\", \"auto\"."
+#~ msgstr ""
+#~ "Výber režimu nastavenia proxy. Podporované hodnoty sú \"none\", \"manual"
+#~ "\", \"auto\"."
+
+#~ msgid "The machine name to proxy FTP through."
+#~ msgstr "Názov počítača, ktorý používať ako proxy pre FTP."
+
+#~ msgid "The machine name to proxy HTTP through."
+#~ msgstr "Názov počítača, ktorý používať ako proxy pre HTTP."
+
+#~ msgid "The machine name to proxy secure HTTP through."
+#~ msgstr "Názov počítača, ktorý používať ako proxy pre zabezpečené HTTP."
+
+#~ msgid "The machine name to proxy socks through."
+#~ msgstr "Názov počítača, ktorý používať ako proxy pre socks."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/http_proxy/host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port počítača definovaného v \"/system/http_proxy/host\", ktorý používate "
+#~ "ako proxy."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/ftp_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port počítača definovaného v \"/system/proxy/ftp_host\", ktorý používate "
+#~ "ako proxy."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/secure_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port počítača definovaného v \"/system/proxy/secure_host\", ktorý "
+#~ "používate ako proxy."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/socks_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port počítača definovaného v \"/system/proxy/socks_host\", ktorý "
+#~ "používate ako proxy."
+
+#~ msgid ""
+#~ "This key contains a list of hosts which are connected to directly, rather "
+#~ "than via the proxy (if it is active). The values can be hostnames, "
+#~ "domains (using an initial wildcard like *.foo.com), IP host addresses "
+#~ "(both IPv4 and IPv6) and network addresses with a netmask (something like "
+#~ "192.168.0.0/24)."
+#~ msgstr ""
+#~ "Tento kľúč obsahuje zoznam hostiteľov, ku ktorým sa radšej pripojiť "
+#~ "priamo a nie cez proxy (ak je atívne). Hodnoty môžu byť názvy hostiteľov, "
+#~ "domény (pomocou počiatočných žolíkov, napr. *.foo.com), IP adresy (IPv4 "
+#~ "aj IPv6) a sieťové adresy s maskou (napr. 192.168.0.0/24)."
+
+#~ msgid "URL that provides proxy configuration values."
+#~ msgstr "URL, ktoré poskytuje hodnoty konfigurácie proxy."
+
+#~ msgid "Use HTTP proxy"
+#~ msgstr "Použiť proxy HTTP"
+
+#~ msgid "User name to pass as authentication when doing HTTP proxying."
+#~ msgstr "Používateľ poskytnutý pri overení totožnosti počas proxy HTTP."
+
+#~ msgid "SMB workgroup"
+#~ msgstr "Pracovná skupina SMB"
+
+#~ msgid ""
+#~ "The Windows networking workgroup or domain that the user is part of. In "
+#~ "order for a new workgroup to fully take effect the user may need to log "
+#~ "out and log back in."
+#~ msgstr ""
+#~ "Sieťová pracovná skupina alebo doména Windows, do ktorej patrí "
+#~ "používateľ. Aby sa nová pracovná skupina úplne prejavila, použivateľ sa "
+#~ "možno bude musieť odhlásiť a prihlásiť."
+
+#~ msgid "Could not initialize gnome vfs"
+#~ msgstr "Nemôžem inicializovať gnome VFS"
+
+#~ msgid "Standard Moniker factory"
+#~ msgstr "Vytváracie rozhranie pre štandardný moniker"
+
+#~ msgid "file MonikerExtender"
+#~ msgstr "súbor MonikerExtender"
+
+#~ msgid "generic Gnome VFS moniker"
+#~ msgstr "generický moniker Gnome VFS"
+
+#, fuzzy
+#~ msgid "generic file moniker"
+#~ msgstr "Všeobecná chyba"
+
+#~ msgid "Display SCSI drives"
+#~ msgstr "Zobraziť SCSI mechaniky"
+
+#~ msgid "Display SCSI optical drives"
+#~ msgstr "Zobraziť optické SCSI mechaniky"
+
+#~ msgid "Display drives with removable media"
+#~ msgstr "Zobraziť mechaniky s výmennými diskami"
+
+#~ msgid "Display external drives"
+#~ msgstr "Zobraziť externé mechaniky"
+
+#~ msgid "Display internal hard drives"
+#~ msgstr "Zobraziť interné pevné disky"
+
+#~ msgid ""
+#~ "Whether to display SCSI optical drives even if /system/storage/"
+#~ "display_scsi_drives is set to FALSE."
+#~ msgstr ""
+#~ "Či sa majú zobraziť optické SCSI disky aj v prípade, že je /system/"
+#~ "storage/display_scsi_drives nastavené na FALSE."
+
+#~ msgid "Whether to display drives and mountable volumes from SCSI drives."
+#~ msgstr "Či sa majú zobraziť mechaniky a pripojiteľné disky z SCSI mechaník."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from drives with "
+#~ "removable media (e.g. drives where media can be inserted and removed)."
+#~ msgstr ""
+#~ "Či sa majú zobraziť mechaniky a pripojiteľné disky z mechaník s výmennými "
+#~ "médiami (mechaniky, do ktorých sa vkladajú disky)."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from external drives (e."
+#~ "g. drives that are hotpluggable; e.g. drives that can be attached and "
+#~ "detached while the system is running)."
+#~ msgstr ""
+#~ "Či sa majú zobraziť mechaniky a pripojiteľné disky z externých mechaník "
+#~ "(mechaniky podporujúce výmenu diskov počas bežiaceho systému)."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from internal hard drives "
+#~ "(non-SCSI optical drives are always shown)."
+#~ msgstr ""
+#~ "Či sa majú zobraziť mechaniky a pripojiteľné disky z interných pevných "
+#~ "diskov (optické ne-SCSI mechaniky sa vždy zobrazia)."
+
+#~ msgid "%s:%d aborted parsing."
+#~ msgstr "%s:%d analýza zlyhala."
+
+#~ msgid "Not a symbolic link"
+#~ msgstr "Nie je symbolický odkaz"
+
+#~ msgid ""
+#~ "Unable to mount the volume. If this is an encrypted drive, then the wrong "
+#~ "password or key was used."
+#~ msgstr ""
+#~ "Nepodarilo sa pripojiť zväzok. Ak je tento zväzok zašifrovaný, bolo "
+#~ "použité nesprávne heslo alebo kľúč."
+
+#~ msgid "Failed to read data from child process %d (%s)"
+#~ msgstr "Čítanie údajov z procesu potomka %d zlyhalo (%s)"
+
+#~ msgid "Couldn't run mount process in a pty"
+#~ msgstr "Proces mount nemohol byť spustený v pty"
+
+#~ msgid "Unexpected error in select() reading data from a child process (%s)"
+#~ msgstr ""
+#~ "Neočakávaná chyba v select() pri čítaní údajov z procesu potomka (%s)"
+
+#~ msgid "Unexpected error in waitpid() (%s)"
+#~ msgstr "Neočakávaná chyba vo waitpid() (%s)"
+
+#~ msgid "Your HTTP Proxy requires you to log in.\n"
+#~ msgstr "Vaše HTTP proxy vyžaduje vaše prihlásenie.\n"
+
+#~ msgid ""
+#~ "You must log in to access \"%s\".\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Aby ste mohli pristupovať k \"%s\", musíte sa prihlásiť.\n"
+#~ "%s"
+
+#~ msgid "Your password will be transmitted unencrypted."
+#~ msgstr "Vaše heslo bude prenesené nezašifrované."
+
+#~ msgid "Your password will be transmitted encrypted."
+#~ msgstr "Vaše heslo bude prenesené zašifrované."
+
+#~ msgid "You must log in to access %s\n"
+#~ msgstr "Aby ste mohli pristupovať k %s, musíte sa prihlásiť\n"
diff --git a/trunk/po/sl.po b/trunk/po/sl.po
new file mode 100644
index 00000000..f3fe10bc
--- /dev/null
+++ b/trunk/po/sl.po
@@ -0,0 +1,1816 @@
+# This file is distributed under the same license as the program package.
+#
+# Matej Urbančič <mateju@svn.gnome.org>, 2008 - 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-23 18:28+0000\n"
+"PO-Revision-Date: 2009-02-24 08:51+0100\n"
+"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
+"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n"
+"X-Poedit-Language: Slovenian\n"
+"X-Poedit-Country: SLOVENIA\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Dejanje ni dovoljeno, saj jo datoteke na različnih priklopnih mestih"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Vrnjena neveljavna vrednost get_info"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Vrnjena neveljavna vrednost query_info"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Ni mogoče pridobiti opisa datoteke pretoka"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Vrnjena neveljavna vrednost open"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Ni bil pridobljen opis datoteke pretoka"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Vrnjena neveljavna vrednost call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Vrnjena neveljavna vrednost get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Ni mogoče najti določene priklopne točke"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Neveljavno ime datoteke %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Vrnjena neveljavna vrednost query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Vrnjena neveljavna vrednost monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Vrnjena neveljavna vrednost monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operacija je bila preklicana"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Napaka v protokolu pretoka: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Konec pretoka"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Iskanje po pretoku ni podprto"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Dejanje info poizvedbe ni podprto"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Poizvedba podrobnosti na pretoku ni podprta"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Napaka med pridobivanjem podrobnosti priklopa_ %s"
+
+#: ../client/gvfsdaemondbus.c:567
+#: ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Napaka s povezovanjem z demonom: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Vrnjena neveljavna vrednost open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Napaka med ustvarjanjem vtiča: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Napaka med povezovanjem z vtičem: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Neveljaven zapis podrobnosti datoteke"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Neveljavna vsebina seznama atributov"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Napaka med zaganjanjem Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Napaka med ustvarjanjem Avahi vtiča: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Napaka med razreševanjem \"%s\" storitve \"%s\" na domeni \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "Napaka med razreševanjem \"%s\" storitve \"%s\" na domeni \"%s\". Manjka en zapis ali več TXT zapisov. Zahtevan ključ: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "časovni pretek razreševanja \"%s\" storitve \"%s\" na domeni \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Neveljaven zapis dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Ni mogoče upravljati z različico %d GVfsIcon kodiranja"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Neveljavno oblikovani vnosni podatki za GVfsIcon"
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Napaka med povezovanjem z D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Datotečni sistem %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Napaka: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Uporaba: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Uporaba: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ni določene vrste pogona"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "priklopna točka %s že teče"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "napaka med zaganjanjem demona priklopa"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ na %s"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Ni določenega imena gostitelja"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836
+#: ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Neveljavno določilo priklopa"
+
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262
+#: ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Datoteka ne obstaja"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Datoteka ni mapa"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Burn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Ni mogoče ustvariti začasne mape"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998
+#: ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Ni take mape ali datoteke"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Mapa ni prazna"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Ni mogoče kopirati datoteke preko mape"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD zapisovalnik"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Datoteka obstaja"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Hrbtenica ne podpira dejanja"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Ni take datoteke ali mape na ciljni poti"
+
+#: ../daemon/gvfsbackendburn.c:877
+#: ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Ni mogoče kopirati mape preko mape"
+
+#: ../daemon/gvfsbackendburn.c:886
+#: ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Ciljna datoteka obstaja"
+
+#: ../daemon/gvfsbackendburn.c:893
+#: ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Ni mogoče kopirati drevesne strukture mape"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371
+#: ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677
+#: ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Ni podprto"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Ni se mogoče povezati s sistemskim vodilom"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Ni mogoče ustvariti libhal vsebine"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Ni mogoče zagnati libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Ni določenega pogona"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Ni mogoče najti pogona %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Pogon %s ne vsebuje zvočnih datotek"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda priklop na %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Zvočni disk"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Datotečni sistem je zaseden: %d odprtih datotek"
+msgstr[1] "Datotečni sistem je zaseden: %d odprta datoteka"
+msgstr[2] "Datotečni sistem je zaseden: %d odprti datoteki"
+msgstr[3] "Datotečni sistem je zaseden: %d odprte datoteke"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Ni take datoteke %s na pogonu %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Napaka programa 'paranoia' na pogonu %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Napaka med iskanjem po pretoku na pogonu %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Ni take datoteke"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Datoteka ne obstaja ali pa ni običajna zvočna sled"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Storitev zvočnega CD datotečnega sistema"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Računalnik"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Datotečni sistem"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Ni mogoče odpreti mape"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Ni mogoče odpreti priklopne datoteke"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Notranja napaka: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Ni mogoče priklopiti datoteke"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Ni medija v pogonu"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Ni priklopna datoteka"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Ni mogoče odklopiti datoteke"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Ni mogoče izvreči datoteke"
+
+#: ../daemon/gvfsbackenddav.c:561
+#: ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Napaka HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Ni mogoče razčleniti odgovora"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Odziv brez vsebine"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Nepričakovan odgovor strežnika"
+
+#: ../daemon/gvfsbackenddav.c:1214
+#: ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Neveljaven odziv"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "Izmenjava WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "Vnos gesla za %s"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Prosim vnesite geslo namestniškega strežnika"
+
+#: ../daemon/gvfsbackenddav.c:1697
+#: ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Ni podprta WebDAV souporaba"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV na %s"
+
+#: ../daemon/gvfsbackenddav.c:1789
+#: ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "Ni mogoče ustvariti zahteve"
+
+#: ../daemon/gvfsbackenddav.c:1925
+#: ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289
+#: ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Ciljna datoteka že obstaja"
+
+#: ../daemon/gvfsbackenddav.c:1998
+#: ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Datoteka je bila zunanje spremenjena"
+
+#: ../daemon/gvfsbackenddav.c:2029
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Ni mogoče ustvariti varnostne kopije"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492
+#: ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Krajevno omrežje"
+
+#: ../daemon/gvfsbackenddnssd.c:736
+#: ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Ni mogoče nadzirati datoteke ali mape."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755
+#: ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882
+#: ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Omrežje"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Računi niso podprti"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Gostitelj je prekinil povezavo"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Ni mogoče odpreti podatkovne povezave. Najverjetneje dejanje preprečuje požarni zid."
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Podatkovna povezava je zaprta"
+
+#: ../daemon/gvfsbackendftp.c:273
+#: ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "Operacija ni uspela"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Na strežniku ni več prostora"
+
+#: ../daemon/gvfsbackendftp.c:290
+#: ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Operacija ni podprta"
+
+#: ../daemon/gvfsbackendftp.c:294
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Dovoljenje zavrnjeno"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Neznana vrsta strani"
+
+#: ../daemon/gvfsbackendftp.c:302
+#: ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Neveljavno ime datoteke"
+
+#: ../daemon/gvfsbackendftp.c:306
+#: ../daemon/gvfsbackendftp.c:388
+#: ../daemon/gvfsbackendftp.c:413
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "neveljaven odgovor"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "prekinjeno oddajanje"
+
+#: ../daemon/gvfsbackendftp.c:710
+#: ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Ni se mogoče povezati z gostiteljem"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Vnesite geslo za ftp uporabnika %s na %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Vnos gesla za ftp na %s"
+
+#: ../daemon/gvfsbackendftp.c:1523
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Vnos gesla je preklican"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp na %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp kot %s na %s"
+
+#: ../daemon/gvfsbackendftp.c:1690
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "Datoteka je mapa"
+
+#: ../daemon/gvfsbackendftp.c:1912
+#: ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "izdelava varnostnih kopij ni podprta"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ime datoteke je predolgo"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Neveljavno ciljno ime datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Datoteka ali mapa že obstaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Ni take mape ali datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Neveljavno ime datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Ni podprto"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalni fotoaparat (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832
+#: ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s predvajalnik zvoka"
+
+#: ../daemon/gvfsbackendgphoto2.c:844
+#: ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:846
+#: ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Predvajalnik zvoka"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Ni določene naprave"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "Ni mogoče ustvariti gphoto2 vsebine"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Napaka med ustvarjanjem kamere"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457
+#: ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Napaka med nalaganjem podrobnosti naprave"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Napaka med preverjanjem podrobnosti naprave"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Napaka med pridobivanjem podrobnosti naprave"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Napaka med nastavljanjem povezovalnih vrat kamere"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Napaka med zaganjanjem kamere"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 priklop na %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Ni določene kamere"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Napaka med ustvarjanjem predmeta datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Napaka med prodobivanjem datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Napaka med branjem podatkov iz datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Neveljavno oblikovano določilo ikone '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852
+#: ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Napaka med iskanjem pretoka na kameri %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Ni imenik"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Napaka med pridobivanjem seznama map"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Napaka med pridobivanjem seznama datotek"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Napaka med ustvarjanjem mape"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "Ime že obstaja"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603
+#: ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Novo ime datoteke je predolgo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613
+#: ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Napaka med preimenovanjem mape"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Napaka med preimenovanjem datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Mapa '%s' ni prazna"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Napaka med brisanjem mape"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Napaka med brisanjem datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Ni mogoče pisati v mapo"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Ni mogoče določiti nove datoteke za pripenjanje"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Ni mogoče prebrati datoteke za pripenjanje"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Ni mogoče pridobiti podatkov datoteke za pripenjanje"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Napaka med pisanjem datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Ni podprto (ni ista mapa)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Ni podprto (vir je mapa, cilj je mapa)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Ni podprto (vir je mapa, cilj je obstoječa datoteka)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Ni podprto (vir je datoteka, cilj je mapa)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Napaka HTTP odjemalca: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr "(neveljavno kodiranje)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Opombe map niso podprte"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Omrežje Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Monitor omrežnih mest"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s na %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Podpora za USB ni nameščena."
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Povezava z napravo je bila izgubljena"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Naprava zahteva programsko posodobitev"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh program je nepričakovano zaključen"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Ime gostitelja ni znano"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ni poti do gostitelja"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Strežnik je zavrnil povezavo"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Neuspešna overitev ključa gostitelja"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Ni mogoče oživiti ssh programa"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Ni mogoče oživiti ssh programa: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Časovni zamik prijave je potekel"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Vnesite šifrirno geslo za ključ"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Vnos gesla"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Ni mogoče poslati gesla"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Vseeno prijavi"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Prekliči prijavo"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Istovetnosti oddaljenega računalnika (%s) ni znana.\n"
+"To se zgodi, kadar se prvič prijavite v sistem.\n"
+"\n"
+"Podatki overitve, ki jih pošilja oddaljeni računalnik so %s. V primeru, da želite biti popolnoma prepričani, da je varno nadaljevati, stopite v stik s skrbnikom vašega sistema."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Prijava je preklicana"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Ni mogoče poslati potrdila istovetnosti gostitelja"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Napaka v protokolu"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp za %s na %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp na %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Ni mogoče najti podprtega ssh ukaza"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Napaka"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716
+#: ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816
+#: ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018
+#: ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130
+#: ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468
+#: ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632
+#: ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768
+#: ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856
+#: ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905
+#: ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Prejet neveljaven odgovor"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Naveljavnen ID ikone '%s' v OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Napaka med ustvarjanjem varnostne datoteke: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Ni mogoče ustvariti začasne datoteke"
+
+#: ../daemon/gvfsbackendsftp.c:3694
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Ni mogoče premakniti mape čez mapo"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Zahtevano geslo za mesto %s na %s"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Notranja napaka (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Napaka med priklapljanjem souporabe mape Oken"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Nepodprta vrsta iskanja"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Ni mogoče ustvariti varnostne kopije: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Napaka med brisanjem datoteke: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Napaka med premikanjem datoteke: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Napaka med odstranjevanjem ciljne datoteke: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Ni mogoče po strukturi map premakniti mape"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Storitev Souporabe datotečnega sistema Oken"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Zahtevano geslo za %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Souporaba Oken na %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Napaka med pridobivanjem seznama souporabe s strežnika"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Datoteke ni mogoče priklopiti"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Ni običajna datoteka"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Storitev omrežnega datotečnega sistema Oken"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#: ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Mape smeti ni mogoče izbrisati"
+
+#: ../daemon/gvfsbackendtrash.c:387
+#: ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Predmetov v smeteh ni mogoče spreminjati"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735
+#: ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Smeti"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Neveljavna vrsta hrbtenice"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Napaka med pošiljanjem fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Simbolnih povezav hrbtenica ne podpira"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Neveljavno dbus sporočilo"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Zamenjaj starejšega demona"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Ne zaženi fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS demon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Glavni demon za GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Poskusite \"%s --help\" za več podrobnosti."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Neveljavni argumenti oživljenega podrejenega procesa"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Samodejen priklop ni uspel: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Določeno mesto ni priklopljeno"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Določeno mesto ni podprto"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Mesto je že priklopljeno"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Mesta ni mogoče priklopiti"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Plošča CD-ROM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Prazen CD-ROM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Plošča CD-R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Prazna plošča CD-R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Plošča CD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Prazna plošča CD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Plošča DVD-ROM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Prazen DVD-ROM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Plošča DVD-RAM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Prazna plošča DVD-RAM disk"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Plošča DVD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Prazna plošča DVD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Plošča DVD+R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Prazna plošča DVD+R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Plošča DVD+RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Prazna plošča DVD+RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL disk"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Prazen DVD+R DL disk"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray disk"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Prazen Blu-Ray disk"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Prazen Blu-Ray R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Prazen Blu-Ray RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD disk"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Prazen HD DVD disk"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Prazen HD DVD-R disk"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Prazen HD DVD-RW disk"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO disk"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Prazen MO disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Prazen disk"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s pogon"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s pogon"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disketna enota"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Programski RAID pogon"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Pogon USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA pogon"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI pogon"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire pogon"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tračni pogon"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash pogon"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Spominska kartica"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia pogon"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Pogon SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Pogon Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Pogon Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb pogon"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Pogon za shranjevanje podatkov"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Napaka med odpiranjem medija: ena ali več enot medija je zasedenih."
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Mešani zvočno-podatkovni disk"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s Medij"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s šifrirani podatki"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: napaka med odpiranjem datoteke: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, napaka med pisanjem v standardni odvod"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: napaka med branjem: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: napaka med zapiranjem: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "MESTO... - združi MESTA na standardni odvod."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Združevanje datotek na mestih in pri tiskanju preko standardnega odvoda. Deluje kot orodje cat z razliko, da uporablja gvfs namesto krajevnih datotek. Primer: uporabite lahko nekaj podobnega kot je pot smb://server/resource/file.txt kot mesto združevanja."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Opomba: uporaba cevi preko ukaza cat, če potrebujete možnosti oblikovanja kot so -n, -T in druge."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: manjka mesto"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: napaka med odpiranjem mesta: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: napaka med zaganjanjem programa: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "DATOTEKE... - odpri DATOTEKE z nastavljenim programom."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Odpre datoteke s privzetim programom, ki je nastavljen za odpiranje določene vrste datotek."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Ni mogoče izbrisati smeti"
+#~ msgid "Can't pull trash"
+#~ msgstr "No mogoče povleči smeti"
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+#~ msgid "File unavailable"
+#~ msgstr "Datoteka ni na voljo"
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (v smeteh)"
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Opozorila mape smeti niso podprta"
+
diff --git a/trunk/po/sq.po b/trunk/po/sq.po
new file mode 100644
index 00000000..74b74a6a
--- /dev/null
+++ b/trunk/po/sq.po
@@ -0,0 +1,1615 @@
+# Përkthimi i gvfs në shqip.
+# Copyright (C) 2008 THE gvfs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gvfs package.
+# Laurent Dhima <laurenti@alblinux.net>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-16 12:01+0200\n"
+"PO-Revision-Date: 2008-09-16 11:52+0200\n"
+"Last-Translator: Laurent Dhima <laurenti@alblinux.net>\n"
+"Language-Team: albanian <gnome-albanian-perkthyesit@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Operacion i pasuportuar, file në mount të ndryshëm"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Vlerë e pavlefshme kthimi nga get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Vlerë e pavlefshme kthimi nga query_info"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "E pamundur marrja e përshkruesit të file të stream"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+msgid "Invalid return value from open"
+msgstr "Vlerë e pavlefshme kthimi nga open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+msgid "Didn't get stream file descriptor"
+msgstr "E pamundur marrja e përshkruesit të file të stream"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Vlerë e pavlefshme kthimi nga call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Vlerë e pavlefshme kthimi nga get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "E pamundur gjetja e mount përmbyllës"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) isfuzzy: Check if the unit has been marked fuzzy.
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Emër file i pasaktë %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Vlerë e pavlefshme kthimi nga query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Vlerë e pavlefshme kthimi nga monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Vlerë e pavlefshme kthimi nga monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Gabim në protokollin e stream: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Fundi i stream"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1073 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Operacioni është anulluar"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Vendosja e pozicionit nuk suportohet në stream"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Operacioni i kërkimit të informacioneve nuk suportohet"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Operacioni i kërkimit të informacioneve nuk suportohet në stream"
+
+#: ../client/gdaemonvfs.c:757
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Gabim gjatë rikuperimit të informacioneve në lidhje me mount: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Gabim gjatë lidhjes me demon: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Gabim gjatë krijimit të socket: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Gabim gjatë lidhjes me socket: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Format informacioni file i pavlefshëm"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "Përmbajtje e pavlefshme liste me informacione vetish"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Gabim gjatë lidhjes me D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Shërbimi i file të sistemit %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Gabim: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Përdorimi: %s --spawner ID-DBUS POZICIONI_OBJEKTIT"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Përdorimi: %s KYÇI=VLERA KYÇI=VLERA ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Nuk është specifikuar asnjë lloj montimi"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "pika e montimit për %s është rregullisht në ekzekutim"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "gabim gjatë nisjes së demon të mount"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ tek %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Nuk është specifikuar asnjë emër host"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:609
+msgid "Invalid mount spec"
+msgstr "Specifikë montimi e pavlefshme"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "File nuk ekziston"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "File nuk është një directory"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Masterizimi"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "I pamundur krijimi i directory të përkohshme"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, c-format
+msgid "No such file or directory"
+msgstr "Asnjë file apo directory"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "Directory jo bosh"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "I pamundur kopjimi i file tek directory"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Krijimi i CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "File ekziston"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobpull.c:173 ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135 ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149 ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119 ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150 ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122 ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Operacion i pasuportuar nga backend"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Asnjë file apo directory në pozicionin e destinuar"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "I pamundur kopjimi i directory në directory"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "File objektiv ekziston"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "I pamundur kopjimi rekursiv i directory"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr "Nuk suportohet"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr "E pamundur lidhja me bus e sistemit"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr "I pamundur krijimi i kontekstit libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Cannot initialize libhal"
+msgstr "E pamundur nisja e libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Nuk është specifikuar asnjë njësi"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "E pamundur gjetja e njësisë %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Njësia %s nuk përmban file audio"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "Mount cdda në %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Disk Audio"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "File i sistemit është i zënë: %d file i hapur"
+msgstr[1] "File i sistemit është i zënë: %d file të hapur"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Asnjë file %s në njësinë %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Gabim nag 'paranoia' në njësinë %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Gabim gjatë vendvendosjes në stream në njësinë %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr "Asnjë file"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "File nuk ekziston ose nuk është një pistë audio"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Shërbimi file system CD audio"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Kompjuteri"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "File i sistemit"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:652
+#: ../daemon/gvfsbackendtrash.c:678 ../daemon/gvfsbackendtrash.c:1786
+msgid "Can't open directory"
+msgstr "E pamundur hapja e directory"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "E pamundur hapja e file të montueshëm"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Gabim i brendshëm: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "I pamundur montimi i file"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "Asnjë disk në njësi"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Nuk është një file i montueshëm"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "I pamundur zmontimi i file"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "pamundur nxjerrja jashtë e file"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Gabim HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "I pamundur analizimi i përgjigjes"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Përgjigje bosh"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Përgjigje e papritur nga serveri"
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr "Përgjigje e pavlefshme"
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr "E përbashkët WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr "Shkruaj fjalëkalimin për %s"
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr "Shkruaj fjalëkalimin për proxy"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr "Nuk është një e përbashkët WebDAV e aktivizuar"
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV në %s"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr "I pamundur krijimi i kërkesës"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1808
+msgid "Target file already exists"
+msgstr "File objektiv ekziston rregullisht"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1042
+msgid "The file was externally modified"
+msgstr "File është ndryshuar nga jashtë"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1078
+#: ../daemon/gvfsbackendsmb.c:1825
+msgid "Backup file creation failed"
+msgstr "Krijimi i file backup dështoi"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "I pamundur monitorimi i file apo directory."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Rrjeti"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "Profilet nuk suportohen"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "Host-i ka mbyllur lidhjen"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"E pamundur hapja e lidhjes me të dhëna. Ndoshta bllokohet nga firewall-i "
+"juaj."
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "Lidhja me të dhëna u mbyll"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Operacioni dështoi"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "Nuk ka mbetur më hapësirë në server"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Operacion i pasuportuar"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Nuk u dha leje"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "Lloj i panjohur faqe"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) isfuzzy: Check if the unit has been marked fuzzy.
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Emër i pavlefshëm file"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Përgjigje e pavlefshme"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "transmisioni u ndërpre"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "E pamundur lidhja me host"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Shkruaj fjalëkalimin për ftp tek %s"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Dialogu i fjalëkalimit u anullua"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp tek %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp si %s tek %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "File është një directory"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "backup nuk janë akoma të suportuar"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "emër file tepër i gjatë"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "Emër file objektiv i pavlefshëm"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Directory apo file ekziston"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: asnjë file apo directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: emër i pavlefshëm file"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: nuk suportohet"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Fotokamër dixhitale (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Fotokamër %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Lexues audio %s"
+
+# #-#-#-#-# gnome-icon-theme.HEAD.sq.po (gnome-icon-theme.HEAD) #-#-#-#-#
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# #-#-#-#-# gnome-icon-theme.gnome-2-22.sq.po (gnome-icon-theme.HEAD) #-#-#-#-#
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+# 48x48/emblems/emblem-camera.icon.in.h:1
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "FotoKamër"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Lexues audio"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+msgid "Failed to get folder list"
+msgstr "Rikuperimi i listës së kartelave dështoi"
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr "Nuk është specifikuar asnjë dispozitiv"
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr "I pamundur krijimi i kontekstit gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+msgid "Error creating camera"
+msgstr "Gabim gjatë krijimit të kamerës"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+msgid "Error loading device information"
+msgstr "Gabim gjatë ngarkimit të informacioneve në lidhje me dispozitivin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr "Gabim gjatë leximit të informacioneve në lidhje me dispozitivin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr "aGabim gjatë marrjes së informacioneve në lidhje me dispozitivin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr "Gabim gjatë rregullimit të portës së komunikimit të fotokamerës"
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr "Gabim gjatë nisjes së fotokamerës"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "mount gphoto2 tek %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr "Nuk është specifikuar asnjë kamër"
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr "Gabim gjatë krijimit të objektit file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+msgid "Error getting file"
+msgstr "Gabim gjatë marrjes së file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr "Gabim gjatë marrjes të së dhënave nga file"
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Gabim gjatë vendosjes në stream tek fotokamera «%s»"
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Nuk është një directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2080
+msgid "Failed to get file list"
+msgstr "Rikuperimi i listës së file dështoi"
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+msgid "Error creating directory"
+msgstr "Gabim gjatë krijimit të directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+msgid "Name already exists"
+msgstr "Emri ekziston rregullisht"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+msgid "New name too long"
+msgstr "Emri i ri tepër i gjatë"
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr "Gabim gjatë riemërtimit të directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr "Gabim gjatë riemërtimit të file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Directory '%s' nuk është bosh"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+msgid "Error deleting directory"
+msgstr "Gabim gjatë eleminimit të directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr "Gabim gjatë eleminimit të file"
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+msgid "Can't write to directory"
+msgstr "I pamundur shkrimi në directory"
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr "E pamundur vendosja e një file të ri tek i cili të shtohet"
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr "I pamundur leximi i file tek i cili të shtohet"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr "E pamundur marrja e të dhënave të file tek i cili të shtohet"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr "Gabim gjatë shkrimit të file"
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+msgid "Not supported (not same directory)"
+msgstr "Nuk suportohet (nuk është e njëjta directory)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Non suportohet (origj është directory, dest është directory)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Non suportohet (origj është directory, dest është file ekzistues)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Non suportohet (origj është file, dest është directory)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Gabim i klientit HTTP: %s"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1305 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (kodifikim i pavlefshëm)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Njoftimi i directory nuk suportohet"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Rrjeti Windows"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Rrjeti lokal"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Monitori i rrjetit lokal"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:525
+#: ../daemon/gvfsbackendsmb.c:1298
+#, c-format
+msgid "%s on %s"
+msgstr "%s në %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "Lidhja me dispozitivin humbi"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "Dispozitivi ka nevojë për një përditësim software"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "Programi ssh doli në menyrë të papritur"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Emër i panjohur host"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Asnjë rrugë për tek host"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "Lidhja nuk u pranua nga serveri"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Verifikimi i kyçit të host dështoi"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "E pamundur nisja e programit ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "E pamundur nisja e programit ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Koha skadoi gjatë hyrjes"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Shkruaj fjalën e hyrjes për kyçin"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Shkruaj fjalëkalimin"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "I pamundur dërgimi i fjalëkalimit"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Futu sidoqoftë"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Anullo futjen"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identiteti i kompjuterit në distancë (%s) është i panjohur.\n"
+"Kjo ndodh gjatë hyrjes për herë të parë në një kompjuter.\n"
+"\n"
+"Identiteti i dërguar nga kompjuteri remot është %s. Për të qenë plotësisht "
+"të sigurt që vazhdimi nuk paraqet rrezik, vihuni në kontakt me "
+"administratorin e sistemit."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Dialogu i hyrjes u anullua"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "E pamundur nisja e konfermimit të identitetit të host"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Gabim protokolli"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp në %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "E pamundur gjetja e një komande ssh të suportuar"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Dështim"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "U mor një përgjigje e pavlefshme"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Gabim gjatë krijimit të file backup: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "I pamundur krijimi i file të përkohshëm"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1797
+msgid "Can't move directory over directory"
+msgstr "E pamundur lëvizja e directory tek directory"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Kërkohet fjalëkalimi për bashkëndarjen %s tek %s"
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Gabim i brendshëm (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:573
+msgid "Failed to mount Windows share"
+msgstr "Montimi i bashkëndarjes Windows dështoi"
+
+#: ../daemon/gvfsbackendsmb.c:721 ../daemon/gvfsbackendsmb.c:1177
+msgid "Unsupported seek type"
+msgstr "Lloj i pasuportuar vendvendosje"
+
+#: ../daemon/gvfsbackendsmb.c:1241
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Kriji i file backup dështoi: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1699
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Gabim gjtë eleminimit të file: %s"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) variables: translation contains variables not in original: %s, %s
+# (pofilter) isfuzzy: Check if the unit has been marked fuzzy.
+# (pofilter) singlequoting: checks whether singlequoting is consistent between the two strings
+# (pofilter) printf: checks whether printf format strings match
+#: ../daemon/gvfsbackendsmb.c:1773
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Gabim gjatë lëvizjes së file: %s"
+
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) variables: translation contains variables not in original: %s, %s
+# (pofilter) isfuzzy: Check if the unit has been marked fuzzy.
+# (pofilter) singlequoting: checks whether singlequoting is consistent between the two strings
+# (pofilter) printf: checks whether printf format strings match
+#: ../daemon/gvfsbackendsmb.c:1845
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Gabim gjatë heqjes së file objektiv: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1869
+msgid "Can't recursively move directory"
+msgstr "E pamundur lëvizja rekursive e directory"
+
+#: ../daemon/gvfsbackendsmb.c:1932
+msgid "Windows Shares Filesystem Service"
+msgstr "Shërbimi file system bashkëndarje Windows"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Të përbashkët Windows në %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "File nuk është i montueshëm"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Nuk është një file i rregullt"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Shërbimi file system rrjeti Windows"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Koshi"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (në kosh)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "I pamundur eleminimi i koshit"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Njoftimi i directory të koshit nuk suportohet"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Lloj backend i pavlefshëm"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Gabim gjatë dërgimit të fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Lidhjet simbolike nuk suportohen nga backend"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Mesazh dbus i pavlefshëm"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Zëvendëson demon-in e vjetër."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Mos nis fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Demon-i GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Demon-i kryesor për GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Provo \"%s --help\" për më shumë informacione."
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "Argumentë të pavlefshëm për birin e gjeneruar"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Montimi automatik dështoi: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "Pozicioni i specifikuar nuk është i montuar"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "Pozicioni i specifikuar nuk suportohet"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "Pozicioni është rregullisht i montuar"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "Pozicioni nuk është i montueshëm"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+# #-#-#-#-# gnome-vfs.HEAD.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) startcaps: checks that the message starts with the correct capitalisation
+# #-#-#-#-# gnome-vfs.gnome-2-22.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) startcaps: checks that the message starts with the correct capitalisation
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Njësi %s/%s"
+
+# #-#-#-#-# gnome-vfs.HEAD.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# (pofilter) startcaps: checks that the message starts with the correct capitalisation
+# #-#-#-#-# gnome-vfs.gnome-2-22.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# (pofilter) startcaps: checks that the message starts with the correct capitalisation
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Njësi %s"
+
+# #-#-#-#-# gnome-vfs.HEAD.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# #-#-#-#-# gnome-vfs.gnome-2-22.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Njësi floppy"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Njësi RAID software"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Njësi USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Njësi ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Njësi SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Njësi FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Njësi me shirit"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Njësi CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Njësi MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Njësi SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Njësi SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Njësi Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Njësi Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Pendrive"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Njësi magazinimi"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Nxjerrja jashtë e suportit dështoi: një apo më shumë volume në suport janë "
+"të zënë."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+# #-#-#-#-# gnome-vfs.HEAD.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+# #-#-#-#-# gtk+.HEAD.sq.po (gtk+ HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# #-#-#-#-# gnome-vfs.gnome-2-22.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+# #-#-#-#-# gnome-vfs.HEAD.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# #-#-#-#-# glib.HEAD.sq.po (glib HEAD) #-#-#-#-#
+# (pofilter) untranslated: checks whether a string has been translated at all
+# #-#-#-#-# gtk+.HEAD.sq.po (gtk+ HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+# #-#-#-#-# gnome-vfs.gnome-2-22.sq.po (gnome-vfs HEAD) #-#-#-#-#
+# (pofilter) unchanged: please translate
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Disk i përzier audio/të dhëna"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Suport prej %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s me të dhëna të kriptuara"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Disk CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Disk bosh CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Disk CD-R"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Disk bosh CD-R"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Disk CD-RW"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Disk bosh CD-RW"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Disk DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Disk bosh DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Disk DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Disk bosh DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Disk DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Disk bosh DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Disk DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Disk bosh DVD+R"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Disk DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Disk bosh DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Disk DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Disk bosh DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Disk Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Disk bosh Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Disk Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Disk bosh Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Disk Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Disk bosh Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Disk HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Disk bosh HD DVD"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Disk HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Disk bosh HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Disk HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Disk bosh HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Disk MO"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Disk bosh MO"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Disk bosh"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: gabim gjatë hapjes së file: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, gabim gjatë shkrimit në stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: gabim gjatë leximit: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: gabim gjatë mbylljes: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "POZICIONI... - vë në rresht POZICIONET tek standard output."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Lidh file tek pozicionet dhe i printon në standard output. Funksionon si "
+"vegla e zakonshme cat, por duke përdorur pozicionet gvfs në vend të file "
+"lokalë: për shembull mund të përdoret diçka e ngjashme me smb://server/"
+"rezerva/file.txt si pozicion për lidhje."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Shënim: vini në pipe me cat nëse nevoiten opsione formatimi si -n, -T apo të "
+"tjerë."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: pozicione mungues"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: gabim gjatë hapjes së pozicionit: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: gabim gjatë nisjes së aplikativit: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILE... - hap FILE me aplikativin përkatës."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Hap file me aplikativin e paracaktuar të regjistruar për të trajtuar llojin "
+"e file."
diff --git a/trunk/po/sr.po b/trunk/po/sr.po
new file mode 100644
index 00000000..c14f21a3
--- /dev/null
+++ b/trunk/po/sr.po
@@ -0,0 +1,2737 @@
+# Serbian translation of gnome-vfs
+# Courtesy of Prevod.org team (http://prevod.org/) -- 2003, 2004, 2005, 2006, 2007.
+#
+# This file is distributed under the same license as the gnome-vfs package.
+#
+# Maintainer: Душан Живојнов <calvin@verat.net>
+# Reviewed on 2004-02-03 by: Данило Шеган <dsegan@gmx.net>
+# Reviewed on 2005-07-08 by: Данило Шеган <dsegan@gmx.net>
+# Reviewed on 2005-09-22 by: Данило Шеган <danilo@prevod.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gnome-vfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-14 18:11+0200\n"
+"PO-Revision-Date: 2007-09-06 21:18+0100\n"
+"Last-Translator: Горан Ракић <grakic@devbase.net>\n"
+"Language-Team: Serbian (sr) <gnom@prevod.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+#, fuzzy
+msgid "Could not find enclosing mount"
+msgstr "Не могу пронаћи главни разгледач"
+
+#: ../client/gdaemonfile.c:1677
+#, fuzzy, c-format
+msgid "Invalid filename %s"
+msgstr "Неисправно име датотеке"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+#, fuzzy
+msgid "End of stream"
+msgstr "Крај датотеке"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, fuzzy
+msgid "Operation was cancelled"
+msgstr "Радња је обустављена"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:515
+#, fuzzy
+msgid "Invalid file info format"
+msgstr "Неисправно име датотеке"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, fuzzy, c-format
+msgid "%s Filesystem Service"
+msgstr "Систем датотека"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr ""
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+#, fuzzy
+msgid "Invalid mount spec"
+msgstr "Неисправни параметри"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, fuzzy, c-format
+msgid "File doesn't exist"
+msgstr "Датотека постоји"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+#, fuzzy
+msgid "The file is not a directory"
+msgstr "Није фасцикла"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, fuzzy, c-format
+msgid "No such file or directory"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "Директоријум није празан"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "Датотека постоји"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+#, fuzzy
+msgid "Target file exists"
+msgstr "Датотека постоји"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1428
+#, fuzzy
+msgid "Cannot initialize libhal"
+msgstr "Не могу да покренем Бонобо"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Звучни диск"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, fuzzy, c-format
+msgid "No such file %s on drive %s"
+msgstr "Нема више простора на уређају"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Систем датотека"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+#, fuzzy
+msgid "Can't open directory"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, fuzzy, c-format
+msgid "Internal error: %s"
+msgstr "Унутрашња грешка"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:520
+#, fuzzy
+msgid "Could not parse response"
+msgstr "Не могу рашчланити: %s"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1304
+#, fuzzy
+msgid "Please enter proxy password"
+msgstr "Лозинка HTTP посредника"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+#, fuzzy
+msgid "Could not create request"
+msgstr "Не могу рашчланити: %s"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Мрежа"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+#, fuzzy
+msgid "Operation failed"
+msgstr "Радња је обустављена"
+
+#: ../daemon/gvfsbackendftp.c:264
+#, fuzzy
+msgid "No space left on server"
+msgstr "Нема више простора на уређају"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+#, fuzzy
+msgid "Operation unsupported"
+msgstr "Радња је заустављена"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+#, fuzzy
+msgid "Permission denied"
+msgstr "Пристип одбијен"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Неисправно име датотеке"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+#, fuzzy
+msgid "Invalid reply"
+msgstr "Неисправна адреса"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+#, fuzzy
+msgid "File is directory"
+msgstr "Датотека је празна"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1828
+#, fuzzy
+msgid "filename too long"
+msgstr "Име је предугачко"
+
+#: ../daemon/gvfsbackendftp.c:2345
+#, fuzzy
+msgid "Invalid destination filename"
+msgstr "Неисправно име датотеке"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, fuzzy, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "Неисправно име датотеке"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, fuzzy, c-format
+msgid "Digital Camera (%s)"
+msgstr "%s %s дигитални фотоапарат"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, fuzzy, c-format
+msgid "%s Camera"
+msgstr "Фотоапарат"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, fuzzy, c-format
+msgid "%s Audio Player"
+msgstr "%s %s пуштач музике"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Фотоапарат"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+#, fuzzy
+msgid "Audio Player"
+msgstr "%s %s пуштач музике"
+
+# bug: inconsistent wording with above "Bookmark saving failed" [eg. "Failed to save a bookmark" would be one way to solve it]
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+#, fuzzy
+msgid "Failed to get folder list"
+msgstr "Неуспешно отварање датотеке „%s“: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+#, fuzzy
+msgid "Error creating camera"
+msgstr "Грешка при покретању наредбе"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+#, fuzzy
+msgid "Error loading device information"
+msgstr "Грешка при покретању наредбе"
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+#, fuzzy
+msgid "Error getting file"
+msgstr "Неуспешна пријава"
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Није фасцикла"
+
+# bug: inconsistent wording with above "Bookmark saving failed" [eg. "Failed to save a bookmark" would be one way to solve it]
+#: ../daemon/gvfsbackendgphoto2.c:2080
+#, fuzzy
+msgid "Failed to get file list"
+msgstr "Неуспешно отварање датотеке „%s“: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+#, fuzzy
+msgid "Error creating directory"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+#, fuzzy
+msgid "Name already exists"
+msgstr "Датотека постоји"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+#, fuzzy
+msgid "New name too long"
+msgstr "Име је предугачко"
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, fuzzy, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Директоријум није празан"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, fuzzy
+msgid "Error deleting directory"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+#, fuzzy
+msgid "Can't write to directory"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+#, fuzzy
+msgid "Not supported (not same directory)"
+msgstr "Није фасцикла"
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+#, fuzzy
+msgid " (invalid encoding)"
+msgstr " (неисправан Уникод)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr ""
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windows мрежа"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+#, fuzzy
+msgid "Local Network"
+msgstr "Мрежа"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:296
+#, fuzzy
+msgid "Hostname not known"
+msgstr "Име рачунара није исправно"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:860
+#, fuzzy
+msgid "Enter password"
+msgstr "Лозинка HTTP посредника"
+
+#: ../daemon/gvfsbackendsftp.c:921
+#, fuzzy
+msgid "Can't send password"
+msgstr "Не могу да пошаљем лозинку процесу који прикључује"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Ипак се пријави"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Откажи пријаву"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, fuzzy, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Ово се догађа када се по први пут пријавите на рачунар.\n"
+"\n"
+"Идентитет који је послао удаљени рачунар је %s. Уколико желите да будете "
+"потпуно сигурни да је безбедно да наставите, ступите у везу са "
+"администратором система."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Грешка у протоколу"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1543
+#, fuzzy
+msgid "Unable to find supported ssh command"
+msgstr "Неуспешно покретање наредбе"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+#, fuzzy
+msgid "Failure"
+msgstr "Датотеке"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+#, fuzzy
+msgid "Invalid reply received"
+msgstr "Неисправни параметри"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, fuzzy, c-format
+msgid "Internal Error (%s)"
+msgstr "Унутрашња грешка"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+#, fuzzy
+msgid "Failed to mount Windows share"
+msgstr "Не могу да одспојим прикључени сервер"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+#, fuzzy
+msgid "Unsupported seek type"
+msgstr "Операција није подржана"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, fuzzy, c-format
+msgid "Error moving file: %s"
+msgstr "Неуспешно чување обележивача (%s)"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1928
+#, fuzzy
+msgid "Windows Shares Filesystem Service"
+msgstr "Дељени Windows диск"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, fuzzy, c-format
+msgid "Windows shares on %s"
+msgstr "Дељени Windows диск"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+#, fuzzy
+msgid "Windows Network Filesystem Service"
+msgstr "Windows мрежа"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1330
+#, fuzzy
+msgid "Can't delete trash"
+msgstr "Баратај trash адресама"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+#, fuzzy
+msgid "Invalid backend type"
+msgstr "Неисправни параметри"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr ""
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+#, fuzzy
+msgid "Operation not supported by backend"
+msgstr "Операција није дозвољена"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:120
+#, fuzzy
+msgid "Invalid dbus message"
+msgstr "Неисправно име датотеке"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr ""
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr ""
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+#, fuzzy
+msgid "HDDVD"
+msgstr "ДВД"
+
+#: ../monitor/hal/ghaldrive.c:158
+#, fuzzy
+msgid "HDDVD-r"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+#, fuzzy
+msgid "HDDVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr ""
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s диск"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s диск"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Дискета"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "УСБ диск"
+
+#: ../monitor/hal/ghaldrive.c:192
+#, fuzzy
+msgid "ATA Drive"
+msgstr "Уређај"
+
+#: ../monitor/hal/ghaldrive.c:194
+#, fuzzy
+msgid "SCSI Drive"
+msgstr "УСБ диск"
+
+#: ../monitor/hal/ghaldrive.c:196
+#, fuzzy
+msgid "FireWire Drive"
+msgstr "Зип диск"
+
+#: ../monitor/hal/ghaldrive.c:200
+#, fuzzy
+msgid "Tape Drive"
+msgstr "Зип диск"
+
+#: ../monitor/hal/ghaldrive.c:202
+#, fuzzy
+msgid "CompactFlash Drive"
+msgstr "Компактни-флеш диск (CF)"
+
+# Чаробни штапић? :)
+#: ../monitor/hal/ghaldrive.c:204
+#, fuzzy
+msgid "MemoryStick Drive"
+msgstr "Меморијски штапић"
+
+#: ../monitor/hal/ghaldrive.c:206
+#, fuzzy
+msgid "SmartMedia Drive"
+msgstr "Мудри носач (SM)"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC носач"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Зип диск"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Џез диск"
+
+#: ../monitor/hal/ghaldrive.c:214
+#, fuzzy
+msgid "Thumb Drive"
+msgstr "%s диск"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, fuzzy, c-format
+msgid "%.1f kB"
+msgstr "%.1f КБ"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f МБ"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f ГБ"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+#, fuzzy
+msgid "Mixed Audio/Data Disc"
+msgstr "Звучни диск"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, fuzzy, c-format
+msgid "%s Media"
+msgstr "Мудри носач (SM)"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr ""
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Обичан диск"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+#, fuzzy
+msgid "Blank CD-ROM Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Пиши-бриши диск"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Празан пиши-бриши диск"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Обичан ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#, fuzzy
+msgid "Blank DVD-ROM Disc"
+msgstr "Празан - ДВД меморијски диск"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Меморијски - ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Празан - ДВД меморијски диск"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Пиши-бриши ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Празан пиши-бриши ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Једном уписиви + ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Празан једном уписиви + ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Пиши+бриши ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Празан пиши+бриши ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+#, fuzzy
+msgid "DVD+R DL Disc"
+msgstr "Једном уписиви + ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+#, fuzzy
+msgid "Blank DVD+R DL Disc"
+msgstr "Празан једном уписиви + ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+#, fuzzy
+msgid "Blu-Ray Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+#, fuzzy
+msgid "Blank Blu-Ray Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+#, fuzzy
+msgid "Blu-Ray R Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+#, fuzzy
+msgid "Blank Blu-Ray R Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+#, fuzzy
+msgid "Blu-Ray RW Disc"
+msgstr "Празан пиши-бриши диск"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+#, fuzzy
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Празан пиши-бриши диск"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+#, fuzzy
+msgid "HD DVD Disc"
+msgstr "Једном уписиви - ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+#, fuzzy
+msgid "Blank HD DVD Disc"
+msgstr "Празан једном уписиви - ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+#, fuzzy
+msgid "HD DVD-R Disc"
+msgstr "Једном уписиви - ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+#, fuzzy
+msgid "Blank HD DVD-R Disc"
+msgstr "Празан једном уписиви - ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+#, fuzzy
+msgid "HD DVD-RW Disc"
+msgstr "Пиши-бриши ДВД диск"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+#, fuzzy
+msgid "Blank HD DVD-RW Disc"
+msgstr "Празан пиши-бриши ДВД диск"
+
+# bug: Compact Disk Disk?
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+#, fuzzy
+msgid "MO Disc"
+msgstr "ЦД диск"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+#, fuzzy
+msgid "Blank MO Disc"
+msgstr "Празан једном-уписив диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+#, fuzzy
+msgid "Disc"
+msgstr "Диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+#, fuzzy
+msgid "Blank Disc"
+msgstr "Празан једном-уписив диск"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
+#~ msgid "ISO 9660 Volume"
+#~ msgstr "ИСО 9660 диск"
+
+#~ msgid "%s:%u contains NUL characters."
+#~ msgstr "%s:%u садржи NUL знакове."
+
+#~ msgid "%s:%u contains no method name."
+#~ msgstr "%s:%u не садржи име метода."
+
+#~ msgid "%s:%u has no options endmarker."
+#~ msgstr "%s:%u не садржи ознаку краја опција."
+
+#~ msgid "%s:%u has unknown options %s."
+#~ msgstr "%s:%u користи непознате опције %s."
+
+#~ msgid "%s:%u contains no module name."
+#~ msgstr "%s:%u не садржи име модула."
+
+#~ msgid "Configuration file `%s' was not found: %s"
+#~ msgstr "Датотека са подешавањима „%s“ није нађена: %s"
+
+#~ msgid "%s:%d aborted parsing."
+#~ msgstr "%s:%d је прекинуо рашчлањивање."
+
+#~ msgid "AFFS Volume"
+#~ msgstr "AFFS диск"
+
+#~ msgid "AFS Network Volume"
+#~ msgstr "Мрежни AFS диск"
+
+#~ msgid "Auto-detected Volume"
+#~ msgstr "Самопрепознати диск"
+
+#~ msgid "CD-ROM Drive"
+#~ msgstr "ЦД уређај"
+
+#~ msgid "CD Digital Audio"
+#~ msgstr "Музички диск"
+
+# bug(slobo): хм, не бих рекао
+#~ msgid "Hardware Device Volume"
+#~ msgstr "Диск на хардверском уређају"
+
+#~ msgid "EncFS Volume"
+#~ msgstr "EncFS диск"
+
+# bug: does it differentiate between Hurd Ext2 and Linux Ext2?
+#~ msgid "Ext2 Linux Volume"
+#~ msgstr "Линукс Ext2 диск"
+
+#~ msgid "Ext3 Linux Volume"
+#~ msgstr "Линукс Ext3 диск"
+
+#~ msgid "MSDOS Volume"
+#~ msgstr "МСДОС диск"
+
+#~ msgid "BSD Volume"
+#~ msgstr "БСД диск"
+
+#~ msgid "FUSE Volume"
+#~ msgstr "ФУСЕ јединица"
+
+#~ msgid "MacOS Volume"
+#~ msgstr "МекОС диск"
+
+# ЦеДе диск, а не „Компактни диск диск“
+#~ msgid "CDROM Volume"
+#~ msgstr "ЦД јединица"
+
+#~ msgid "Hsfs CDROM Volume"
+#~ msgstr "Hsfs ЦД јединица"
+
+#~ msgid "JFS Volume"
+#~ msgstr "ЈФС диск"
+
+#~ msgid "Windows NT Volume"
+#~ msgstr "Windows NT диск"
+
+#~ msgid "System Volume"
+#~ msgstr "Системски диск"
+
+#~ msgid "Memory Volume"
+#~ msgstr "Меморијски диск"
+
+#~ msgid "Minix Volume"
+#~ msgstr "Миникс диск"
+
+#~ msgid "NFS Network Volume"
+#~ msgstr "Диск мрежног система датотека"
+
+#~ msgid "Netware Volume"
+#~ msgstr "Netware диск"
+
+#~ msgid "Reiser4 Linux Volume"
+#~ msgstr "Линукс Рајзер4 диск"
+
+#~ msgid "ReiserFS Linux Volume"
+#~ msgstr "Линукс РајзерФС диск"
+
+#~ msgid "SuperMount Volume"
+#~ msgstr "SuperMount диск"
+
+#~ msgid "DVD Volume"
+#~ msgstr "ДВД јединица"
+
+#~ msgid "Solaris/BSD Volume"
+#~ msgstr "Соларис/БСД диск"
+
+#~ msgid "Udfs Solaris Volume"
+#~ msgstr "Соларис Udfs диск"
+
+#~ msgid "Pcfs Solaris Volume"
+#~ msgstr "Соларис Pcfs диск"
+
+#~ msgid "Sun SAM-QFS Volume"
+#~ msgstr "Sun SAM-QFS диск"
+
+#~ msgid "Temporary Volume"
+#~ msgstr "Привремени диск"
+
+#~ msgid "Enhanced DOS Volume"
+#~ msgstr "Унапређени DOS диск"
+
+#~ msgid "Windows VFAT Volume"
+#~ msgstr "Windows VFAT диск"
+
+#~ msgid "Xenix Volume"
+#~ msgstr "Xenix диск"
+
+#~ msgid "XFS Linux Volume"
+#~ msgstr "Линукс XFS диск"
+
+#~ msgid "XIAFS Volume"
+#~ msgstr "XIAFS диск"
+
+#~ msgid "CIFS Volume"
+#~ msgstr "CIFS диск"
+
+#~ msgid "Unknown"
+#~ msgstr "Непознат"
+
+#~ msgid "%s Volume"
+#~ msgstr "%s диск"
+
+# :)
+#~ msgid "Pen Drive"
+#~ msgstr "Оловкасти диск"
+
+#~ msgid "External %s"
+#~ msgstr "Спољни %s"
+
+#~ msgid "%s Removable Volume"
+#~ msgstr "Уклоњиви %s диск"
+
+#~ msgid "Volume"
+#~ msgstr "Диск"
+
+#~ msgid "Unknown operation type %u"
+#~ msgstr "Непознат тип операције %u"
+
+#~ msgid "Cannot create pipe for open GIOChannel: %s"
+#~ msgstr "Не могу направити цевку за отворени GIOChannel: %s"
+
+#~ msgid "Unknown job kind %u"
+#~ msgstr "Непозната врста посла %u"
+
+#~ msgid ""
+#~ "Deprecated function. User modifications to the MIME database are no "
+#~ "longer supported."
+#~ msgstr ""
+#~ "Превазиђена функција. Измене корисника у МИМЕ бази више нису подржане."
+
+#~ msgid "More parsing errors will be ignored."
+#~ msgstr "Остале грешке у обради ће бити занемарене."
+
+#~ msgid "No error"
+#~ msgstr "Нема грешке"
+
+#~ msgid "File not found"
+#~ msgstr "Датотека није нађена"
+
+#~ msgid "Generic error"
+#~ msgstr "Општа грешка"
+
+#~ msgid "I/O error"
+#~ msgstr "У/И грешка"
+
+#~ msgid "Data corrupted"
+#~ msgstr "Подаци оштећени"
+
+#~ msgid "Format not valid"
+#~ msgstr "Облик није исправан"
+
+# bug: is file handle the same as file descriptor?
+#~ msgid "Bad file handle"
+#~ msgstr "Лоша ручка датотеке"
+
+#~ msgid "File too big"
+#~ msgstr "Датотека је превелика"
+
+#~ msgid "Read-only file system"
+#~ msgstr "Систем датотека само за читање"
+
+#~ msgid "File not open"
+#~ msgstr "Датотека није отворена"
+
+#~ msgid "Open mode not valid"
+#~ msgstr "Начин отварања није исправан"
+
+#~ msgid "Too many open files"
+#~ msgstr "Превише отворених датотека"
+
+#~ msgid "Operation in progress"
+#~ msgstr "Операција у току"
+
+#~ msgid "Operation interrupted"
+#~ msgstr "Операција прекинута"
+
+#~ msgid "Looping links encountered"
+#~ msgstr "Пронађене кружне везе"
+
+#~ msgid "Is a directory"
+#~ msgstr "Јесте фасцикла"
+
+#~ msgid "Not enough memory"
+#~ msgstr "Нема довољно меморије"
+
+#~ msgid "Host not found"
+#~ msgstr "Рачунар није нађен"
+
+#~ msgid "Host has no address"
+#~ msgstr "Рачунар нема адресу"
+
+#~ msgid "Directory busy"
+#~ msgstr "Заузет директоријум"
+
+#~ msgid "Too many links"
+#~ msgstr "Превише веза"
+
+#~ msgid "Read only file system"
+#~ msgstr "Неуписив систем датотека"
+
+#~ msgid "Not on the same file system"
+#~ msgstr "Није на истом систему датотека"
+
+#~ msgid "Service not available"
+#~ msgstr "Услуга није доступна"
+
+#~ msgid "Request obsoletes service's data"
+#~ msgstr "Захтев застарева податке услуге"
+
+#~ msgid "No default action associated"
+#~ msgstr "Није додељено уобичајено дејство"
+
+#~ msgid "No handler for URL scheme"
+#~ msgstr "Нема руковаоца за врсту адресе (URL-а)"
+
+#~ msgid "Error parsing command line"
+#~ msgstr "Грешка при читању наредбе"
+
+#~ msgid "Timeout reached"
+#~ msgstr "Достигнут рок"
+
+#~ msgid "Nameserver error"
+#~ msgstr "Грешка са сервером имена"
+
+#~ msgid "The resource is locked"
+#~ msgstr "Ресурс је закључан"
+
+#~ msgid "Function call deprecated"
+#~ msgstr "Позив функције је превазиђен"
+
+#~ msgid "Not a symbolic link"
+#~ msgstr "Није симболичка веза"
+
+#~ msgid "Unknown error"
+#~ msgstr "Непозната грешка"
+
+#~ msgid "%u byte"
+#~ msgid_plural "%u bytes"
+#~ msgstr[0] "%u бајт"
+#~ msgstr[1] "%u бајта"
+#~ msgstr[2] "%u бајтова"
+
+#~ msgid "Floppy"
+#~ msgstr "Дискета"
+
+#~ msgid "CD-ROM/DVD-ROM"
+#~ msgstr "ЦД-РОМ/ДВД-РОМ"
+
+#~ msgid "CD-ROM/DVD-RAM"
+#~ msgstr "ЦД-РОМ/ДВД-РАМ"
+
+#~ msgid "CD-ROM/DVD-R"
+#~ msgstr "ЦД-РОМ/ДВД-Р"
+
+#~ msgid "CD-ROM/DVD-RW"
+#~ msgstr "ЦД-РОМ/ДВД-РВ"
+
+#~ msgid "CD-R/DVD-ROM"
+#~ msgstr "ЦД-Р/ДВД-РОМ"
+
+#~ msgid "CD-R/DVD-RAM"
+#~ msgstr "ЦД-Р/ДВД-РАМ"
+
+#~ msgid "CD-R/DVD-R"
+#~ msgstr "ЦД-Р/ДВД-Р"
+
+#~ msgid "CD-R/DVD-RW"
+#~ msgstr "ЦД-Р/ДВД-РВ"
+
+#~ msgid "CD-RW/DVD-ROM"
+#~ msgstr "ЦД-РВ/ДВД-РОМ"
+
+#~ msgid "CD-RW/DVD-RAM"
+#~ msgstr "ЦД-РВ/ДВД-РАМ"
+
+#~ msgid "CD-RW/DVD-R"
+#~ msgstr "ЦД-РВ/ДВД-Р"
+
+#~ msgid "CD-RW/DVD-RW"
+#~ msgstr "ЦД-РВ/ДВД-РВ"
+
+#~ msgid "IEEE1394 Drive"
+#~ msgstr "ИЕЕЕ1394 диск"
+
+#~ msgid "CF"
+#~ msgstr "CF"
+
+#~ msgid "SD/MMC"
+#~ msgstr "SD/MMC"
+
+# Чаробни штапић? :)
+#~ msgid "Memory Stick"
+#~ msgstr "Меморијски штапић"
+
+#~ msgid "Root Volume"
+#~ msgstr "Корени диск"
+
+#~ msgid "Audio CD"
+#~ msgstr "Музички диск"
+
+#~ msgid "Unknown volume"
+#~ msgstr "Непознати диск"
+
+#~ msgid "Network server"
+#~ msgstr "Мрежни сервер"
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. There is probably no floppy in the "
+#~ "drive."
+#~ msgstr "Не могу да прикључим дискету. Вероватно дискета није у уређају. "
+
+#~ msgid ""
+#~ "Unable to mount the volume. There is probably no media in the device."
+#~ msgstr "Не могу да прикључим диск. Вероватно нема носача у уређају. "
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. The floppy is probably in a format that "
+#~ "cannot be mounted."
+#~ msgstr ""
+#~ "Не могу да прикључим дискету. Вероватно је дискета у запису који се не "
+#~ "може читати."
+
+#~ msgid ""
+#~ "Unable to mount the volume. If this is an encrypted drive, then the wrong "
+#~ "password or key was used."
+#~ msgstr ""
+#~ "Не могу да прикључим диск. Ако је он шифрован, тада је била искоришћена "
+#~ "погрешна лозинка или кључ."
+
+#~ msgid ""
+#~ "Unable to mount the selected volume. The volume is probably in a format "
+#~ "that cannot be mounted."
+#~ msgstr ""
+#~ "Не могу да прикључим изабрани диск. Вероватно је диск у запису који се не "
+#~ "може читати."
+
+#~ msgid "Unable to mount the selected floppy drive."
+#~ msgstr "Не могу да прикључим изабрану дискету."
+
+#~ msgid "Unable to mount the selected volume."
+#~ msgstr "Не могу да прикључим изабрани диск."
+
+#~ msgid ""
+#~ "Unable to unmount the selected volume. The volume is in use by one or "
+#~ "more programs."
+#~ msgstr ""
+#~ "Не могу да одспојим изабрани диск. Њега вероватно користи неки програм "
+#~ "или програми."
+
+#~ msgid "Unable to unmount the selected volume."
+#~ msgstr "Не могу да одспојим изабрани диск."
+
+#~ msgid "Failed to read data from child process %d (%s)"
+#~ msgstr "Неуспешно читање датотеке из наследног процеса %d (%s)"
+
+#~ msgid "Couldn't run mount process in a pty"
+#~ msgstr "Не могу да покренем процес прикључења у лажном терминалу"
+
+#~ msgid "Unexpected error in select() reading data from a child process (%s)"
+#~ msgstr ""
+#~ "Неочекивана грешка у функцији select() при читању података у наследном "
+#~ "процесу (%s)"
+
+#~ msgid "Unexpected error in waitpid() (%s)"
+#~ msgstr "Неочекивана грешка унутар извршења функције waitpid() (%s)"
+
+#~ msgid "Unable to eject media"
+#~ msgstr "Не могу да избацим носач"
+
+#~ msgid "Home"
+#~ msgstr "Лични"
+
+#~ msgid "Unknown GnomeVFSSeekPosition %d"
+#~ msgstr "Непознато GnomeVFSSeekPosition %d"
+
+#~ msgid "The identity of the remote computer (%s) is unknown."
+#~ msgstr "Идентитет удаљеног рачунара (%s) није познат."
+
+#~ msgid "Didn't find a valid settings file at %s\n"
+#~ msgstr "Нисам нашао исправну датотеку са подешавањима у %s\n"
+
+#~ msgid "Use the %s environment variable to specify a different location.\n"
+#~ msgstr "Користите променљиву окружења %s да назначите другу путању.\n"
+
+#~ msgid "Your HTTP Proxy requires you to log in.\n"
+#~ msgstr "Ваш ХТТП посредник захтева пријаву.\n"
+
+#~ msgid ""
+#~ "You must log in to access \"%s\".\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Морате се пријавити како бисте приступили „%s“.\n"
+#~ "%s"
+
+#~ msgid "Your password will be transmitted unencrypted."
+#~ msgstr "Лозинка ће бити пренета незаштићена."
+
+#~ msgid "Your password will be transmitted encrypted."
+#~ msgstr "Лозинка ће бити шифрована пре преноса."
+
+#~ msgid "You must log in to access %s domain %s\n"
+#~ msgstr "Морате се пријавити како бисте приступили %s, домен %s\n"
+
+#~ msgid "You must log in to access %s\n"
+#~ msgstr "Морате се пријавити како бисте приступили %s\n"
+
+#~ msgid "Default component viewer application"
+#~ msgstr "Подразумевани програм за преглед делова"
+
+#~ msgid "Default terminal application"
+#~ msgstr "Подразумевани терминалски програм"
+
+# bug: no slang, s/exec/execut.../?
+#~ msgid "Exec argument for default terminal"
+#~ msgstr "Аргумент извршавања за подразумевани терминал"
+
+#~ msgid ""
+#~ "The application to use for viewing files that require a component to view "
+#~ "them. The parameter %s will be replaced by the file's URIs, the parameter "
+#~ "%c will be replaced by the component IID."
+#~ msgstr ""
+#~ "Програм који се користи за прегледање датотека које захтевају компоненту "
+#~ "за преглед. Параметар %s ће бити замењен адресом датотеке, а параметар %c "
+#~ "ће бити замењен IID-ом компоненте."
+
+#~ msgid ""
+#~ "The default terminal application to use for applications that require a "
+#~ "terminal."
+#~ msgstr ""
+#~ "Подразумевани терминалски програм који се користи за програме којима је "
+#~ "неопходан терминал."
+
+# bug: no slang, s/exec/execute.../?
+#~ msgid "The exec argument to use for the default terminal application."
+#~ msgstr "Аргумент извршавања за подразумевани терминалски програм."
+
+#~ msgid "Run the command in a terminal"
+#~ msgstr "Покрени наредбу у терминалу"
+
+#~ msgid "The command used to handle \"aim\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „aim“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"callto\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „callto“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"ghelp\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „ghelp“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"h323\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „h323“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"http\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „http“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"https\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „https“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"info\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „info“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"mailto\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „mailto“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"man\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „man“ адресама, ако је укључено."
+
+#~ msgid "The command used to handle \"trash\" URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „trash“ адресама, ако је укључено."
+
+#~ msgid "The handler for \"aim\" URLs"
+#~ msgstr "Руковаоц „aim“ адресама"
+
+#~ msgid "The handler for \"callto\" URLs"
+#~ msgstr "Руковаоц „callto“ адресама"
+
+#~ msgid "The handler for \"ghelp\" URLs"
+#~ msgstr "Руковаоц „ghelp“ адресама"
+
+#~ msgid "The handler for \"h323\" URLs"
+#~ msgstr "Руковаоц „h323“ адресама"
+
+#~ msgid "The handler for \"http\" URLs"
+#~ msgstr "Руковаоц „http“ адресама"
+
+#~ msgid "The handler for \"https\" URLs"
+#~ msgstr "Руковаоц „https“ адресама"
+
+#~ msgid "The handler for \"info\" URLs"
+#~ msgstr "Руковаоц „info“ адресама"
+
+#~ msgid "The handler for \"mailto\" URLs"
+#~ msgstr "Руковаоц „mailto“ адресама"
+
+#~ msgid "The handler for \"man\" URLs"
+#~ msgstr "Руковаоц „man“ адресама"
+
+#~ msgid "The handler for \"trash\" URLs"
+#~ msgstr "Руковаоц „trash“ адресама"
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"aim"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„aim“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"callto\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„callto“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"ghelp"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„ghelp“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"h323"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„h323“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"http"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„http“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"https"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„https“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"info"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„info“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"mailto\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„mailto“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"man"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„man“ адресе."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"trash"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„trash“ адресе."
+
+#~ msgid ""
+#~ "True if the command used to handle this type of URL should be run in a "
+#~ "terminal."
+#~ msgstr ""
+#~ "Укључено ако наредба која се користи за ове адресе треба да се покреће у "
+#~ "терминалу."
+
+#~ msgid "Whether the specified command should handle \"aim\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „aim“ адресе."
+
+#~ msgid "Whether the specified command should handle \"callto\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „callto“ адресе."
+
+#~ msgid "Whether the specified command should handle \"ghelp\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „ghelp“ адресе."
+
+#~ msgid "Whether the specified command should handle \"h323\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „h323“ адресе."
+
+#~ msgid "Whether the specified command should handle \"http\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „http“ адресе."
+
+#~ msgid "Whether the specified command should handle \"https\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „https“ адресе."
+
+#~ msgid "Whether the specified command should handle \"info\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „info“ адресе."
+
+#~ msgid "Whether the specified command should handle \"mailto\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „mailto“ адресе."
+
+#~ msgid "Whether the specified command should handle \"man\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „man“ адресе."
+
+#~ msgid "Whether the specified command should handle \"trash\" URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „trash“ адресе."
+
+#~ msgid ""
+#~ "Comma separated list of DNS-SD domains that should be visible in the "
+#~ "\"network:///\" location."
+#~ msgstr ""
+#~ "Запетом раздвојен списак DNS-SD домена који су доступни на путањи "
+#~ "„network:///."
+
+#~ msgid "Extra domains to look for DNS-SD services in"
+#~ msgstr "Допунски домени на којима да тражи DNS-SD услуге"
+
+#~ msgid "How to display local DNS-SD service"
+#~ msgstr "Како да приказује локалну DNS-SD услугу"
+
+#~ msgid "Possible values are \"merged\", \"separate\" and \"disabled\"."
+#~ msgstr ""
+#~ "Допуштене вредности су „merged“ (спојено), „separate“ (раздвојено) и "
+#~ "„disabled“ (искључено)."
+
+#~ msgid "Authenticate proxy server connections"
+#~ msgstr "Идентификуј везе са посредничким сервером"
+
+#~ msgid "Automatic proxy configuration URL"
+#~ msgstr "Адреса за самоподешавање посредника"
+
+#~ msgid "Enables the proxy settings when accessing HTTP over the Internet."
+#~ msgstr "Укључује подешавања посредника при приступу вебу преко Интернета."
+
+#~ msgid "FTP proxy host name"
+#~ msgstr "Име FTP посредника"
+
+#~ msgid "FTP proxy port"
+#~ msgstr "Порт FTP посредника"
+
+#~ msgid "HTTP proxy host name"
+#~ msgstr "Име HTTP посредника"
+
+#~ msgid "HTTP proxy port"
+#~ msgstr "Порт HTTP посредника"
+
+#~ msgid "HTTP proxy username"
+#~ msgstr "Корисник HTTP посредника"
+
+#~ msgid ""
+#~ "If true, then connections to the proxy server require authentication. The "
+#~ "username/password combo is defined by \"/system/http_proxy/"
+#~ "authentication_user\" and \"/system/http_proxy/authentication_password\"."
+#~ msgstr ""
+#~ "Уколико је постављено, везе са посредничким сервером се идентификују. Пар "
+#~ "корисник/лозинка се узима из „/system/http_proxy/authentication_user“ и „/"
+#~ "system/http_proxy/authentication_password“."
+
+#~ msgid "Non-proxy hosts"
+#~ msgstr "Беспосредничке адресе"
+
+#~ msgid "Password to pass as authentication when doing HTTP proxying."
+#~ msgstr "Лозинка која се користи за идентификацију код веб посредника."
+
+#~ msgid "Proxy configuration mode"
+#~ msgstr "Начин подешавања посредника"
+
+#~ msgid "SOCKS proxy host name"
+#~ msgstr "Име SOCKS посредника"
+
+#~ msgid "SOCKS proxy port"
+#~ msgstr "Порт SOCKS посредника"
+
+#~ msgid "Secure HTTP proxy host name"
+#~ msgstr "Име безбедног HTTP посредника"
+
+#~ msgid "Secure HTTP proxy port"
+#~ msgstr "Порт безбедног HTTP посредника"
+
+#~ msgid ""
+#~ "Select the proxy configuration mode. Supported values are \"none\", "
+#~ "\"manual\", \"auto\"."
+#~ msgstr ""
+#~ "Изаберите режим подешавања посредника. Допуштене вредности су „none“, "
+#~ "„manual“ и „auto“."
+
+#~ msgid "The machine name to proxy FTP through."
+#~ msgstr "Име рачунара за FTP посредовање."
+
+#~ msgid "The machine name to proxy HTTP through."
+#~ msgstr "Име рачунара за веб (HTTP) посредовање."
+
+#~ msgid "The machine name to proxy secure HTTP through."
+#~ msgstr "Име рачунара за безбедно веб (HTTPS) посредовање."
+
+# bug: s/socks/SOCKS/
+#~ msgid "The machine name to proxy socks through."
+#~ msgstr "Име рачунара за SOCKS посредовање."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/http_proxy/host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Порт рачунара датог у „/system/http_proxy/host“ кроз који посредује."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/ftp_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Порт рачунара датог у „/system/proxy/ftp_proxy“ кроз који посредује."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/secure_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Порт рачунара датог у „/system/proxy/secure_proxy“ кроз који посредује."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/socks_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Порт машине одређене помоћу „/system/proxy/socks_proxy“ која је посредник."
+
+#~ msgid ""
+#~ "This key contains a list of hosts which are connected to directly, rather "
+#~ "than via the proxy (if it is active). The values can be hostnames, "
+#~ "domains (using an initial wildcard like *.foo.com), IP host addresses "
+#~ "(both IPv4 and IPv6) and network addresses with a netmask (something like "
+#~ "192.168.0.0/24)."
+#~ msgstr ""
+#~ "Овај кључ садржи списак рачунара који су непосредно повезани, уместо "
+#~ "путем посредника (уколико је у дејству). Ове вредности могу бити имена "
+#~ "рачунара, домени (помоћу почетних навода као што је *.нешто.ију), ИП "
+#~ "адресе рачунара (било ИП4 било ИП6) и адресе мрежа уз мрежну маску (нешто "
+#~ "као што је 192.168.0.0/24)."
+
+#~ msgid "URL that provides proxy configuration values."
+#~ msgstr "Адреса која обезбеђује вредности за подешавање посредника."
+
+#~ msgid "Use HTTP proxy"
+#~ msgstr "Користи веб посредника"
+
+#~ msgid "User name to pass as authentication when doing HTTP proxying."
+#~ msgstr "Корисничко име које се шаље при идентификацији код веб посредника."
+
+#~ msgid "SMB workgroup"
+#~ msgstr "СМБ радна група"
+
+#~ msgid ""
+#~ "The Windows networking workgroup or domain that the user is part of. In "
+#~ "order for a new workgroup to fully take effect the user may need to log "
+#~ "out and log back in."
+#~ msgstr ""
+#~ "Радна група или домен Windows мреже чији је корисник члан. Да би нова "
+#~ "радна група узела маха корисник ће можда морати да се одјави и поново "
+#~ "пријави."
+
+# Гномов Виртуелни Систем Датотека — ВСД? Или Гномово „опонашање система датотека“ — ОСД?
+#~ msgid "Could not initialize gnome vfs"
+#~ msgstr "Не могу да покренем Гномово опонашање система датотека"
+
+#~ msgid "Standard Moniker factory"
+#~ msgstr "Производња обичног надимка"
+
+#~ msgid "file MonikerExtender"
+#~ msgstr "датотека MonikerExtender"
+
+#~ msgid "generic Gnome VFS moniker"
+#~ msgstr "основни надимак Гномовог опонашавача система датотека"
+
+#~ msgid "generic file moniker"
+#~ msgstr "основни надимак датотеке"
+
+#~ msgid "Display SCSI drives"
+#~ msgstr "Прикажи SCSI уређаје"
+
+#~ msgid "Display SCSI optical drives"
+#~ msgstr "Прикажи оптичке SCSI уређаје"
+
+#~ msgid "Display drives with removable media"
+#~ msgstr "Прикажи уређаје са уклоњивим носачима"
+
+#~ msgid "Display external drives"
+#~ msgstr "Прикажи спољашње уређаје"
+
+#~ msgid "Display internal hard drives"
+#~ msgstr "Прикажи унутрашње тврде дискове"
+
+#~ msgid ""
+#~ "Whether to display SCSI optical drives even if /system/storage/"
+#~ "display_scsi_drives is set to FALSE."
+#~ msgstr ""
+#~ "Да ли да приказује оптичке SCSI уређаје чак и ако је /system/storage/"
+#~ "display_scsi_drives искључен."
+
+#~ msgid "Whether to display drives and mountable volumes from SCSI drives."
+#~ msgstr "Да ли да приказује уређаје и прикључиве дискове са SCSI уређаја."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from drives with "
+#~ "removable media (e.g. drives where media can be inserted and removed)."
+#~ msgstr ""
+#~ "Да ли да приказује уређаје и прикључиве дискове са уређаја са уклоњивим "
+#~ "носачима (нпр. уређаји где се носач може убацити и избацити)."
+
+# bug: hotpluggable is technobabble, second part of "eg." should be enough
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from external drives (e."
+#~ "g. drives that are hotpluggable; e.g. drives that can be attached and "
+#~ "detached while the system is running)."
+#~ msgstr ""
+#~ "Да ли да приказује уређаје и прикључиве дискове са спољашњих уређаја "
+#~ "(нпр. уређаји који се могу прикључити у току рада)."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from internal hard drives "
+#~ "(non-SCSI optical drives are always shown)."
+#~ msgstr ""
+#~ "Да ли да приказује уређаје и прикључиве дискове са унутрашњих тврдих "
+#~ "дискова (отпички не-SCSI дискови се увек приказују)."
+
+#~ msgid "The window workgroup the user is part of"
+#~ msgstr "Виндоуз радна група које је корисник члан"
+
+#~ msgid "Optical Disc"
+#~ msgstr "Оптички диск"
+
+# Чаробни штапић? :)
+#~ msgid "Memory Stick Media"
+#~ msgstr "Меморијски штапић (MS)"
+
+#~ msgid "Smart Media Media"
+#~ msgstr "Мудри носач (SM)"
+
+#~ msgid "Mac OS disk"
+#~ msgstr "Мекинтош диск"
+
+#~ msgid "Mac OS X disk"
+#~ msgstr "Мекинтош ОС-Икс диск"
+
+# Транскрипција на нивоу ;-)
+#~ msgid "Windows Disk"
+#~ msgstr "Виндуз диск"
+
+#~ msgid "Linux Disk"
+#~ msgstr "Линукс диск"
+
+#~ msgid "File could not be opened: %s"
+#~ msgstr "Датотека се не може отворити: %s"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain line '%s' which is not an entry, group, or comment"
+#~ msgstr ""
+#~ "„.desktop“ датотека садржи ред „%s“ који није унос, група ни примедба"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries file does not start with legal start group"
+#~ msgstr "„.desktop“ датотека не почиње са исправном почетном групом"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain line '%s' which is not UTF-8"
+#~ msgstr "„.desktop“ датотека садржи ред „%s“ који није УТФ-8"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain unknown encoding '%s'"
+#~ msgstr "„.desktop“ датотека користи непознато кодирање „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries do not have group '%s'"
+#~ msgstr "„.desktop“ датотека нема групу „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries do not have key '%s'"
+#~ msgstr "„.desktop“ датотека нема кључ „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain key '%s' which has value that cannot be "
+#~ "interpreted."
+#~ msgstr ""
+#~ "„.desktop“ датотека садржи кључ „%s“ који има вредност која се не може "
+#~ "разумети."
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain no translated value for key '%s' with locale '%s'."
+#~ msgstr ""
+#~ "„.desktop“ датотека не садржи превод вредности кључа „%s“ у локалитету „%"
+#~ "s“."
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain invalid escape sequence '%s'"
+#~ msgstr "„.desktop“ датотека садржи неисправан знак за истицање „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain escape character at end of line"
+#~ msgstr ""
+#~ "„.desktop“ датотека садржи неисправан знак за истицање на крају реда"
+
+#~ msgid "Value '%s' cannot be interpreted as a number."
+#~ msgstr "Вредност „%s“ се не може посматрати као број."
+
+#~ msgid "Value '%s' cannot be interpreted as a boolean."
+#~ msgstr "Вредност „%s“ се не може посматрати као истинитосна вредност."
+
+#~ msgid "Applications"
+#~ msgstr "Програми"
+
+#~ msgid "Cards"
+#~ msgstr "Карте"
+
+#~ msgid "Folders"
+#~ msgstr "Фасцикле"
+
+#~ msgid "Help"
+#~ msgstr "Помоћ"
+
+#~ msgid "Hosts"
+#~ msgstr "Рачунари"
+
+#~ msgid "Links"
+#~ msgstr "Везе"
+
+#~ msgid "Mail"
+#~ msgstr "Пошта"
+
+#~ msgid "Tools"
+#~ msgstr "Алати"
+
+#~ msgid "Windows"
+#~ msgstr "Прозори"
+
+# bug: inconsistent with other strings which use "...to handle \"h323\" URLs..."
+#~ msgid "The command used to handle HTTP URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „http“ адресама, ако је укључено."
+
+# bug: inconsistent with other strings which use "...to handle \"h323\" URLs..."
+#~ msgid "The command used to handle HTTPS URLs, if enabled."
+#~ msgstr "Наредба коришћена за баратање „https“ адресама, ако је укључено."
+
+# bug: inconsistent with other strings; should be "The handler for \"http\" URLs"
+#~ msgid "The handler for HTTP URLs"
+#~ msgstr "Руковаоц „http“ адресама"
+
+# bug: inconsistent with other strings; should be "The handler for \"https\" URLs"
+#~ msgid "The handler for HTTPS URLs"
+#~ msgstr "Руковаоц „https“ адресама"
+
+# bug: inconsistent; should be "...should handle \"http\" URLs."
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle HTTP "
+#~ "URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„http“ адресе."
+
+# bug: inconsistent; should be "...should handle \"https\" URLs."
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle HTTPS "
+#~ "URLs."
+#~ msgstr ""
+#~ "Укључено ако наредба наведена у кључу „command“ треба да се користи за "
+#~ "„https“ адресе."
+
+# bug: inconsistent; should be "...should handle \"http\" URLs".
+#~ msgid "Whether the specified command should handle HTTP URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „http“ адресе."
+
+# bug: inconsistent; should be "...should handle \"https\" URLs".
+#~ msgid "Whether the specified command should handle HTTPS URLs"
+#~ msgstr "Да ли наведена наредба треба да се користи за „https“ адресе."
+
+#~ msgid "H323 URL handler"
+#~ msgstr "Руковалац H323 адресама"
+
+#~ msgid "HTTP URL handler"
+#~ msgstr "Руковалац HTTP адресама"
+
+#~ msgid "HTTPS URL handler"
+#~ msgstr "Руковалац HTTPS адресама"
+
+#~ msgid "Handle callto URLs"
+#~ msgstr "Баратај callto адресама"
+
+#~ msgid "Handle ghelp URLs"
+#~ msgstr "Баратај ghelp адресама"
+
+#~ msgid "Handle info URLs"
+#~ msgstr "Баратај info адресама"
+
+#~ msgid "Handle mailto URLs"
+#~ msgstr "Баратај mailto адресама"
+
+#~ msgid "Handle man URLs"
+#~ msgstr "Баратај man адресама"
+
+#~ msgid "callto URL handler"
+#~ msgstr "Руковалац callto адресама"
+
+#~ msgid "ghelp URL handler"
+#~ msgstr "Руковалац ghelp адресама"
+
+#~ msgid "info URL handler"
+#~ msgstr "Руковалац info адресама"
+
+#~ msgid "mailto URL handler"
+#~ msgstr "Руковалац mailto адресама"
+
+#~ msgid "man URL handler"
+#~ msgstr "Руковалац man адресама"
+
+#~ msgid "trash URL handler"
+#~ msgstr "Руковалац trash адресама"
+
+#~ msgid "Could not get information for file '%s': %s"
+#~ msgstr "Не могу да сазнам податке о датотеци „%s“: %s"
+
+# bug: as above [inconsistent wording]
+#~ msgid ""
+#~ "Failed to load image '%s': reason not known, probably a corrupt image file"
+#~ msgstr ""
+#~ "Неуспешно учитавање слике „%s“: разлог непознат, вероватно оштећена "
+#~ "датотека слике"
+
+#~ msgid "How to handle http URLs"
+#~ msgstr "Како баратати http адресама"
+
+#~ msgid "How to handle https URLs"
+#~ msgstr "Како баратати https адресама"
+
+#~ msgid "Set to true to have a program specified in command handle https URLs"
+#~ msgstr ""
+#~ "Укључите ако желите да програм наведен у наредби барата https адресама"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/ghelp handle ghelp "
+#~ "URLs"
+#~ msgstr ""
+#~ "Укључите ако желите да програм наведен у programs/ghelp барата ghelp "
+#~ "адресама"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/info handle info URLs"
+#~ msgstr ""
+#~ "Укључите ако желите да програм наведен у programs/info барата info "
+#~ "адресама"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/man handle man URLs"
+#~ msgstr ""
+#~ "Укључите ако желите да програм наведен у programs/man барата man адресама"
+
+#~ msgid "URL handler for h323 uris"
+#~ msgstr "Руковаоц h323 адресама"
+
+#~ msgid "URL handler for http uris"
+#~ msgstr "Руковаоц http адресама"
+
+#~ msgid "URL handler for https uris"
+#~ msgstr "Руковаоц https адресама"
+
+#~ msgid "Hosts are not contacted via the proxy"
+#~ msgstr "Рачунарима се не приступа преко посредника"
+
+#~ msgid "The machine name to proxy http through."
+#~ msgstr "Име рачунара HTTP посредника."
+
+#~ msgid "Use proxy settings when accessing http"
+#~ msgstr "Користи подешавања посредника при приступу вебу"
+
+#~ msgid "http proxy username"
+#~ msgstr "Корисничко име HTTP посредника"
+
+# bug: plural-forms
+#~ msgid "1 byte"
+#~ msgstr "1 бајт"
diff --git a/trunk/po/sr@latin.po b/trunk/po/sr@latin.po
new file mode 100644
index 00000000..6423519a
--- /dev/null
+++ b/trunk/po/sr@latin.po
@@ -0,0 +1,2737 @@
+# Serbian translation of gnome-vfs
+# Courtesy of Prevod.org team (http://prevod.org/) -- 2003, 2004, 2005, 2006, 2007.
+#
+# This file is distributed under the same license as the gnome-vfs package.
+#
+# Maintainer: Dušan Živojnov <calvin@verat.net>
+# Reviewed on 2004-02-03 by: Danilo Šegan <dsegan@gmx.net>
+# Reviewed on 2005-07-08 by: Danilo Šegan <dsegan@gmx.net>
+# Reviewed on 2005-09-22 by: Danilo Šegan <danilo@prevod.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gnome-vfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-14 18:11+0200\n"
+"PO-Revision-Date: 2007-09-06 21:18+0100\n"
+"Last-Translator: Goran Rakić <grakic@devbase.net>\n"
+"Language-Team: Serbian (sr) <gnom@prevod.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1979
+msgid "Operation not supported, files on different mounts"
+msgstr ""
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2234
+#: ../client/gdaemonfile.c:2312 ../client/gdaemonfile.c:2571
+msgid "Invalid return value from open"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2202
+msgid "Didn't get stream file descriptor"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr ""
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr ""
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+#, fuzzy
+msgid "Could not find enclosing mount"
+msgstr "Ne mogu pronaći glavni razgledač"
+
+#: ../client/gdaemonfile.c:1677
+#, fuzzy, c-format
+msgid "Invalid filename %s"
+msgstr "Neispravno ime datoteke"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2124
+msgid "Invalid return value from monitor_dir"
+msgstr ""
+
+#: ../client/gdaemonfile.c:2173
+msgid "Invalid return value from monitor_file"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+#, fuzzy
+msgid "End of stream"
+msgstr "Kraj datoteke"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1069 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, fuzzy
+msgid "Operation was cancelled"
+msgstr "Radnja je obustavljena"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr ""
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr ""
+
+#: ../client/gdaemonvfs.c:749
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr ""
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr ""
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr ""
+
+#: ../common/gvfsdaemonprotocol.c:515
+#, fuzzy
+msgid "Invalid file info format"
+msgstr "Neispravno ime datoteke"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr ""
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, fuzzy, c-format
+msgid "%s Filesystem Service"
+msgstr "Sistem datoteka"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr ""
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr ""
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr ""
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr ""
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr ""
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr ""
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:605
+#, fuzzy
+msgid "Invalid mount spec"
+msgstr "Neispravni parametri"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:822
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, fuzzy, c-format
+msgid "File doesn't exist"
+msgstr "Datoteka postoji"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+#, fuzzy
+msgid "The file is not a directory"
+msgstr "Nije fascikla"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, fuzzy, c-format
+msgid "No such file or directory"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "Direktorijum nije prazan"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:897
+msgid "Can't copy file over directory"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:917 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "Datoteka postoji"
+
+#: ../daemon/gvfsbackendburn.c:845
+msgid "No such file or directory in target path"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:868
+msgid "Can't copy directory over directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:877
+#, fuzzy
+msgid "Target file exists"
+msgstr "Datoteka postoji"
+
+#: ../daemon/gvfsbackendburn.c:884
+msgid "Can't recursively copy directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendburn.c:943 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:223 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:233 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:246 ../daemon/gvfsbackendgphoto2.c:1428
+#, fuzzy
+msgid "Cannot initialize libhal"
+msgstr "Ne mogu da pokrenem Bonobo"
+
+#: ../daemon/gvfsbackendcdda.c:261 ../daemon/gvfsbackendcdda.c:332
+msgid "No drive specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:276
+#, c-format
+msgid "Cannot find drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:286
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr ""
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:294
+#, c-format
+msgid "cdda mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:295 ../daemon/gvfsbackendcdda.c:799
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:214
+#: ../monitor/hal/ghalvolume.c:235
+#, c-format
+msgid "Audio Disc"
+msgstr "Zvučni disk"
+
+#: ../daemon/gvfsbackendcdda.c:356 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: ../daemon/gvfsbackendcdda.c:546
+#, fuzzy, c-format
+msgid "No such file %s on drive %s"
+msgstr "Nema više prostora na uređaju"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:655
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:718
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:815 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:829
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr ""
+
+#: ../daemon/gvfsbackendcdda.c:935
+msgid "Audio CD Filesystem Service"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Sistem datoteka"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:648
+#: ../daemon/gvfsbackendtrash.c:678
+#, fuzzy
+msgid "Can't open directory"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, fuzzy, c-format
+msgid "Internal error: %s"
+msgstr "Unutrašnja greška"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr ""
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:520
+#, fuzzy
+msgid "Could not parse response"
+msgstr "Ne mogu raščlaniti: %s"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1304
+#, fuzzy
+msgid "Please enter proxy password"
+msgstr "Lozinka HTTP posrednika"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+#, fuzzy
+msgid "Could not create request"
+msgstr "Ne mogu raščlaniti: %s"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1804
+msgid "Target file already exists"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1038
+msgid "The file was externally modified"
+msgstr ""
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1074
+#: ../daemon/gvfsbackendsmb.c:1821
+msgid "Backup file creation failed"
+msgstr ""
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr ""
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr ""
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Mreža"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+#, fuzzy
+msgid "Operation failed"
+msgstr "Radnja je obustavljena"
+
+#: ../daemon/gvfsbackendftp.c:264
+#, fuzzy
+msgid "No space left on server"
+msgstr "Nema više prostora na uređaju"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+#, fuzzy
+msgid "Operation unsupported"
+msgstr "Radnja je zaustavljena"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+#, fuzzy
+msgid "Permission denied"
+msgstr "Pristip odbijen"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Neispravno ime datoteke"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+#, fuzzy
+msgid "Invalid reply"
+msgstr "Neispravna adresa"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr ""
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+#, fuzzy
+msgid "File is directory"
+msgstr "Datoteka je prazna"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr ""
+
+#: ../daemon/gvfsbackendftp.c:1828
+#, fuzzy
+msgid "filename too long"
+msgstr "Ime je predugačko"
+
+#: ../daemon/gvfsbackendftp.c:2345
+#, fuzzy
+msgid "Invalid destination filename"
+msgstr "Neispravno ime datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, fuzzy, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "Neispravno ime datoteke"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, fuzzy, c-format
+msgid "Digital Camera (%s)"
+msgstr "%s %s digitalni fotoaparat"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, fuzzy, c-format
+msgid "%s Camera"
+msgstr "Fotoaparat"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, fuzzy, c-format
+msgid "%s Audio Player"
+msgstr "%s %s puštač muzike"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Fotoaparat"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+#, fuzzy
+msgid "Audio Player"
+msgstr "%s %s puštač muzike"
+
+# bug: inconsistent wording with above "Bookmark saving failed" [eg. "Failed to save a bookmark" would be one way to solve it]
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+#, fuzzy
+msgid "Failed to get folder list"
+msgstr "Neuspešno otvaranje datoteke „%s“: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+#, fuzzy
+msgid "Error creating camera"
+msgstr "Greška pri pokretanju naredbe"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+#, fuzzy
+msgid "Error loading device information"
+msgstr "Greška pri pokretanju naredbe"
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr ""
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+#, fuzzy
+msgid "Error getting file"
+msgstr "Neuspešna prijava"
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Nije fascikla"
+
+# bug: inconsistent wording with above "Bookmark saving failed" [eg. "Failed to save a bookmark" would be one way to solve it]
+#: ../daemon/gvfsbackendgphoto2.c:2080
+#, fuzzy
+msgid "Failed to get file list"
+msgstr "Neuspešno otvaranje datoteke „%s“: %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+#, fuzzy
+msgid "Error creating directory"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+#, fuzzy
+msgid "Name already exists"
+msgstr "Datoteka postoji"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+#, fuzzy
+msgid "New name too long"
+msgstr "Ime je predugačko"
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, fuzzy, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Direktorijum nije prazan"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, fuzzy
+msgid "Error deleting directory"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+#, fuzzy
+msgid "Can't write to directory"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+#, fuzzy
+msgid "Not supported (not same directory)"
+msgstr "Nije fascikla"
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1301 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+#, fuzzy
+msgid " (invalid encoding)"
+msgstr " (neispravan Unikod)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr ""
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windows mreža"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+#, fuzzy
+msgid "Local Network"
+msgstr "Mreža"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr ""
+
+#. Mount was successful
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:557
+#: ../daemon/gvfsbackendsmb.c:1294
+#, c-format
+msgid "%s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:296
+#, fuzzy
+msgid "Hostname not known"
+msgstr "Ime računara nije ispravno"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:860
+#, fuzzy
+msgid "Enter password"
+msgstr "Lozinka HTTP posrednika"
+
+#: ../daemon/gvfsbackendsftp.c:921
+#, fuzzy
+msgid "Can't send password"
+msgstr "Ne mogu da pošaljem lozinku procesu koji priključuje"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "Ipak se prijavi"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Otkaži prijavu"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, fuzzy, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Ovo se događa kada se po prvi put prijavite na računar.\n"
+"\n"
+"Identitet koji je poslao udaljeni računar je %s. Ukoliko želite da budete "
+"potpuno sigurni da je bezbedno da nastavite, stupite u vezu sa "
+"administratorom sistema."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Greška u protokolu"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:1543
+#, fuzzy
+msgid "Unable to find supported ssh command"
+msgstr "Neuspešno pokretanje naredbe"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+#, fuzzy
+msgid "Failure"
+msgstr "Datoteke"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+#, fuzzy
+msgid "Invalid reply received"
+msgstr "Neispravni parametri"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1793
+msgid "Can't move directory over directory"
+msgstr ""
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:216
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:471 ../daemon/gvfsbackendsmb.c:511
+#: ../daemon/gvfsdaemonutils.c:92
+#, fuzzy, c-format
+msgid "Internal Error (%s)"
+msgstr "Unutrašnja greška"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:550
+#, fuzzy
+msgid "Failed to mount Windows share"
+msgstr "Ne mogu da odspojim priključeni server"
+
+#: ../daemon/gvfsbackendsmb.c:717 ../daemon/gvfsbackendsmb.c:1173
+#, fuzzy
+msgid "Unsupported seek type"
+msgstr "Operacija nije podržana"
+
+#: ../daemon/gvfsbackendsmb.c:1237
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1695
+#, c-format
+msgid "Error deleting file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1769
+#, fuzzy, c-format
+msgid "Error moving file: %s"
+msgstr "Neuspešno čuvanje obeleživača (%s)"
+
+#: ../daemon/gvfsbackendsmb.c:1841
+#, c-format
+msgid "Error removing target file: %s"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1865
+msgid "Can't recursively move directory"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmb.c:1928
+#, fuzzy
+msgid "Windows Shares Filesystem Service"
+msgstr "Deljeni Windows disk"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, fuzzy, c-format
+msgid "Windows shares on %s"
+msgstr "Deljeni Windows disk"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+#, fuzzy
+msgid "Windows Network Filesystem Service"
+msgstr "Windows mreža"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:1330
+#, fuzzy
+msgid "Can't delete trash"
+msgstr "Barataj trash adresama"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr ""
+
+#: ../daemon/gvfsdaemon.c:1032
+#, fuzzy
+msgid "Invalid backend type"
+msgstr "Neispravni parametri"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr ""
+
+#: ../daemon/gvfsjobcloseread.c:112 ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169 ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151 ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192 ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256 ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109 ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168 ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148 ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobupload.c:169
+#: ../daemon/gvfsjobwrite.c:120
+#, fuzzy
+msgid "Operation not supported by backend"
+msgstr "Operacija nije dozvoljena"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr ""
+
+#: ../daemon/gvfsjobsetattribute.c:120
+#, fuzzy
+msgid "Invalid dbus message"
+msgstr "Neispravno ime datoteke"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr ""
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr ""
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr ""
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr ""
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr ""
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr ""
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr ""
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr ""
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr ""
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr ""
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+#, fuzzy
+msgid "HDDVD"
+msgstr "DVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+#, fuzzy
+msgid "HDDVD-r"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:160
+#, fuzzy
+msgid "HDDVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr ""
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s disk"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s disk"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disketa"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB disk"
+
+#: ../monitor/hal/ghaldrive.c:192
+#, fuzzy
+msgid "ATA Drive"
+msgstr "Uređaj"
+
+#: ../monitor/hal/ghaldrive.c:194
+#, fuzzy
+msgid "SCSI Drive"
+msgstr "USB disk"
+
+#: ../monitor/hal/ghaldrive.c:196
+#, fuzzy
+msgid "FireWire Drive"
+msgstr "Zip disk"
+
+#: ../monitor/hal/ghaldrive.c:200
+#, fuzzy
+msgid "Tape Drive"
+msgstr "Zip disk"
+
+#: ../monitor/hal/ghaldrive.c:202
+#, fuzzy
+msgid "CompactFlash Drive"
+msgstr "Kompaktni-fleš disk (CF)"
+
+# Čarobni štapić? :)
+#: ../monitor/hal/ghaldrive.c:204
+#, fuzzy
+msgid "MemoryStick Drive"
+msgstr "Memorijski štapić"
+
+#: ../monitor/hal/ghaldrive.c:206
+#, fuzzy
+msgid "SmartMedia Drive"
+msgstr "Mudri nosač (SM)"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC nosač"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip disk"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Džez disk"
+
+#: ../monitor/hal/ghaldrive.c:214
+#, fuzzy
+msgid "Thumb Drive"
+msgstr "%s disk"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr ""
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:152
+#, fuzzy, c-format
+msgid "%.1f kB"
+msgstr "%.1f KB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:157
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:162
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:233
+#, fuzzy
+msgid "Mixed Audio/Data Disc"
+msgstr "Zvučni disk"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:244
+#, fuzzy, c-format
+msgid "%s Media"
+msgstr "Mudri nosač (SM)"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:221
+#, c-format
+msgid "%s Encrypted Data"
+msgstr ""
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Običan disk"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+#, fuzzy
+msgid "Blank CD-ROM Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Piši-briši disk"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Prazan piši-briši disk"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Običan DVD disk"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#, fuzzy
+msgid "Blank DVD-ROM Disc"
+msgstr "Prazan - DVD memorijski disk"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Memorijski - DVD disk"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Prazan - DVD memorijski disk"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Piši-briši DVD disk"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Prazan piši-briši DVD disk"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Jednom upisivi + DVD disk"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Prazan jednom upisivi + DVD disk"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Piši+briši DVD disk"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Prazan piši+briši DVD disk"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+#, fuzzy
+msgid "DVD+R DL Disc"
+msgstr "Jednom upisivi + DVD disk"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+#, fuzzy
+msgid "Blank DVD+R DL Disc"
+msgstr "Prazan jednom upisivi + DVD disk"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+#, fuzzy
+msgid "Blu-Ray Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+#, fuzzy
+msgid "Blank Blu-Ray Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+#, fuzzy
+msgid "Blu-Ray R Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+#, fuzzy
+msgid "Blank Blu-Ray R Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+#, fuzzy
+msgid "Blu-Ray RW Disc"
+msgstr "Prazan piši-briši disk"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+#, fuzzy
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Prazan piši-briši disk"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+#, fuzzy
+msgid "HD DVD Disc"
+msgstr "Jednom upisivi - DVD disk"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+#, fuzzy
+msgid "Blank HD DVD Disc"
+msgstr "Prazan jednom upisivi - DVD disk"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+#, fuzzy
+msgid "HD DVD-R Disc"
+msgstr "Jednom upisivi - DVD disk"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+#, fuzzy
+msgid "Blank HD DVD-R Disc"
+msgstr "Prazan jednom upisivi - DVD disk"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+#, fuzzy
+msgid "HD DVD-RW Disc"
+msgstr "Piši-briši DVD disk"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+#, fuzzy
+msgid "Blank HD DVD-RW Disc"
+msgstr "Prazan piši-briši DVD disk"
+
+# bug: Compact Disk Disk?
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+#, fuzzy
+msgid "MO Disc"
+msgstr "CD disk"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+#, fuzzy
+msgid "Blank MO Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+#, fuzzy
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+#, fuzzy
+msgid "Blank Disc"
+msgstr "Prazan jednom-upisiv disk"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr ""
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr ""
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr ""
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+
+#~ msgid "ISO 9660 Volume"
+#~ msgstr "ISO 9660 disk"
+
+#~ msgid "%s:%u contains NUL characters."
+#~ msgstr "%s:%u sadrži NUL znakove."
+
+#~ msgid "%s:%u contains no method name."
+#~ msgstr "%s:%u ne sadrži ime metoda."
+
+#~ msgid "%s:%u has no options endmarker."
+#~ msgstr "%s:%u ne sadrži oznaku kraja opcija."
+
+#~ msgid "%s:%u has unknown options %s."
+#~ msgstr "%s:%u koristi nepoznate opcije %s."
+
+#~ msgid "%s:%u contains no module name."
+#~ msgstr "%s:%u ne sadrži ime modula."
+
+#~ msgid "Configuration file `%s' was not found: %s"
+#~ msgstr "Datoteka sa podešavanjima „%s“ nije nađena: %s"
+
+#~ msgid "%s:%d aborted parsing."
+#~ msgstr "%s:%d je prekinuo raščlanjivanje."
+
+#~ msgid "AFFS Volume"
+#~ msgstr "AFFS disk"
+
+#~ msgid "AFS Network Volume"
+#~ msgstr "Mrežni AFS disk"
+
+#~ msgid "Auto-detected Volume"
+#~ msgstr "Samoprepoznati disk"
+
+#~ msgid "CD-ROM Drive"
+#~ msgstr "CD uređaj"
+
+#~ msgid "CD Digital Audio"
+#~ msgstr "Muzički disk"
+
+# bug(slobo): hm, ne bih rekao
+#~ msgid "Hardware Device Volume"
+#~ msgstr "Disk na hardverskom uređaju"
+
+#~ msgid "EncFS Volume"
+#~ msgstr "EncFS disk"
+
+# bug: does it differentiate between Hurd Ext2 and Linux Ext2?
+#~ msgid "Ext2 Linux Volume"
+#~ msgstr "Linuks Ext2 disk"
+
+#~ msgid "Ext3 Linux Volume"
+#~ msgstr "Linuks Ext3 disk"
+
+#~ msgid "MSDOS Volume"
+#~ msgstr "MSDOS disk"
+
+#~ msgid "BSD Volume"
+#~ msgstr "BSD disk"
+
+#~ msgid "FUSE Volume"
+#~ msgstr "FUSE jedinica"
+
+#~ msgid "MacOS Volume"
+#~ msgstr "MekOS disk"
+
+# CeDe disk, a ne „Kompaktni disk disk“
+#~ msgid "CDROM Volume"
+#~ msgstr "CD jedinica"
+
+#~ msgid "Hsfs CDROM Volume"
+#~ msgstr "Hsfs CD jedinica"
+
+#~ msgid "JFS Volume"
+#~ msgstr "JFS disk"
+
+#~ msgid "Windows NT Volume"
+#~ msgstr "Windows NT disk"
+
+#~ msgid "System Volume"
+#~ msgstr "Sistemski disk"
+
+#~ msgid "Memory Volume"
+#~ msgstr "Memorijski disk"
+
+#~ msgid "Minix Volume"
+#~ msgstr "Miniks disk"
+
+#~ msgid "NFS Network Volume"
+#~ msgstr "Disk mrežnog sistema datoteka"
+
+#~ msgid "Netware Volume"
+#~ msgstr "Netware disk"
+
+#~ msgid "Reiser4 Linux Volume"
+#~ msgstr "Linuks Rajzer4 disk"
+
+#~ msgid "ReiserFS Linux Volume"
+#~ msgstr "Linuks RajzerFS disk"
+
+#~ msgid "SuperMount Volume"
+#~ msgstr "SuperMount disk"
+
+#~ msgid "DVD Volume"
+#~ msgstr "DVD jedinica"
+
+#~ msgid "Solaris/BSD Volume"
+#~ msgstr "Solaris/BSD disk"
+
+#~ msgid "Udfs Solaris Volume"
+#~ msgstr "Solaris Udfs disk"
+
+#~ msgid "Pcfs Solaris Volume"
+#~ msgstr "Solaris Pcfs disk"
+
+#~ msgid "Sun SAM-QFS Volume"
+#~ msgstr "Sun SAM-QFS disk"
+
+#~ msgid "Temporary Volume"
+#~ msgstr "Privremeni disk"
+
+#~ msgid "Enhanced DOS Volume"
+#~ msgstr "Unapređeni DOS disk"
+
+#~ msgid "Windows VFAT Volume"
+#~ msgstr "Windows VFAT disk"
+
+#~ msgid "Xenix Volume"
+#~ msgstr "Xenix disk"
+
+#~ msgid "XFS Linux Volume"
+#~ msgstr "Linuks XFS disk"
+
+#~ msgid "XIAFS Volume"
+#~ msgstr "XIAFS disk"
+
+#~ msgid "CIFS Volume"
+#~ msgstr "CIFS disk"
+
+#~ msgid "Unknown"
+#~ msgstr "Nepoznat"
+
+#~ msgid "%s Volume"
+#~ msgstr "%s disk"
+
+# :)
+#~ msgid "Pen Drive"
+#~ msgstr "Olovkasti disk"
+
+#~ msgid "External %s"
+#~ msgstr "Spoljni %s"
+
+#~ msgid "%s Removable Volume"
+#~ msgstr "Uklonjivi %s disk"
+
+#~ msgid "Volume"
+#~ msgstr "Disk"
+
+#~ msgid "Unknown operation type %u"
+#~ msgstr "Nepoznat tip operacije %u"
+
+#~ msgid "Cannot create pipe for open GIOChannel: %s"
+#~ msgstr "Ne mogu napraviti cevku za otvoreni GIOChannel: %s"
+
+#~ msgid "Unknown job kind %u"
+#~ msgstr "Nepoznata vrsta posla %u"
+
+#~ msgid ""
+#~ "Deprecated function. User modifications to the MIME database are no "
+#~ "longer supported."
+#~ msgstr ""
+#~ "Prevaziđena funkcija. Izmene korisnika u MIME bazi više nisu podržane."
+
+#~ msgid "More parsing errors will be ignored."
+#~ msgstr "Ostale greške u obradi će biti zanemarene."
+
+#~ msgid "No error"
+#~ msgstr "Nema greške"
+
+#~ msgid "File not found"
+#~ msgstr "Datoteka nije nađena"
+
+#~ msgid "Generic error"
+#~ msgstr "Opšta greška"
+
+#~ msgid "I/O error"
+#~ msgstr "U/I greška"
+
+#~ msgid "Data corrupted"
+#~ msgstr "Podaci oštećeni"
+
+#~ msgid "Format not valid"
+#~ msgstr "Oblik nije ispravan"
+
+# bug: is file handle the same as file descriptor?
+#~ msgid "Bad file handle"
+#~ msgstr "Loša ručka datoteke"
+
+#~ msgid "File too big"
+#~ msgstr "Datoteka je prevelika"
+
+#~ msgid "Read-only file system"
+#~ msgstr "Sistem datoteka samo za čitanje"
+
+#~ msgid "File not open"
+#~ msgstr "Datoteka nije otvorena"
+
+#~ msgid "Open mode not valid"
+#~ msgstr "Način otvaranja nije ispravan"
+
+#~ msgid "Too many open files"
+#~ msgstr "Previše otvorenih datoteka"
+
+#~ msgid "Operation in progress"
+#~ msgstr "Operacija u toku"
+
+#~ msgid "Operation interrupted"
+#~ msgstr "Operacija prekinuta"
+
+#~ msgid "Looping links encountered"
+#~ msgstr "Pronađene kružne veze"
+
+#~ msgid "Is a directory"
+#~ msgstr "Jeste fascikla"
+
+#~ msgid "Not enough memory"
+#~ msgstr "Nema dovoljno memorije"
+
+#~ msgid "Host not found"
+#~ msgstr "Računar nije nađen"
+
+#~ msgid "Host has no address"
+#~ msgstr "Računar nema adresu"
+
+#~ msgid "Directory busy"
+#~ msgstr "Zauzet direktorijum"
+
+#~ msgid "Too many links"
+#~ msgstr "Previše veza"
+
+#~ msgid "Read only file system"
+#~ msgstr "Neupisiv sistem datoteka"
+
+#~ msgid "Not on the same file system"
+#~ msgstr "Nije na istom sistemu datoteka"
+
+#~ msgid "Service not available"
+#~ msgstr "Usluga nije dostupna"
+
+#~ msgid "Request obsoletes service's data"
+#~ msgstr "Zahtev zastareva podatke usluge"
+
+#~ msgid "No default action associated"
+#~ msgstr "Nije dodeljeno uobičajeno dejstvo"
+
+#~ msgid "No handler for URL scheme"
+#~ msgstr "Nema rukovaoca za vrstu adrese (URL-a)"
+
+#~ msgid "Error parsing command line"
+#~ msgstr "Greška pri čitanju naredbe"
+
+#~ msgid "Timeout reached"
+#~ msgstr "Dostignut rok"
+
+#~ msgid "Nameserver error"
+#~ msgstr "Greška sa serverom imena"
+
+#~ msgid "The resource is locked"
+#~ msgstr "Resurs je zaključan"
+
+#~ msgid "Function call deprecated"
+#~ msgstr "Poziv funkcije je prevaziđen"
+
+#~ msgid "Not a symbolic link"
+#~ msgstr "Nije simbolička veza"
+
+#~ msgid "Unknown error"
+#~ msgstr "Nepoznata greška"
+
+#~ msgid "%u byte"
+#~ msgid_plural "%u bytes"
+#~ msgstr[0] "%u bajt"
+#~ msgstr[1] "%u bajta"
+#~ msgstr[2] "%u bajtova"
+
+#~ msgid "Floppy"
+#~ msgstr "Disketa"
+
+#~ msgid "CD-ROM/DVD-ROM"
+#~ msgstr "CD-ROM/DVD-ROM"
+
+#~ msgid "CD-ROM/DVD-RAM"
+#~ msgstr "CD-ROM/DVD-RAM"
+
+#~ msgid "CD-ROM/DVD-R"
+#~ msgstr "CD-ROM/DVD-R"
+
+#~ msgid "CD-ROM/DVD-RW"
+#~ msgstr "CD-ROM/DVD-RV"
+
+#~ msgid "CD-R/DVD-ROM"
+#~ msgstr "CD-R/DVD-ROM"
+
+#~ msgid "CD-R/DVD-RAM"
+#~ msgstr "CD-R/DVD-RAM"
+
+#~ msgid "CD-R/DVD-R"
+#~ msgstr "CD-R/DVD-R"
+
+#~ msgid "CD-R/DVD-RW"
+#~ msgstr "CD-R/DVD-RV"
+
+#~ msgid "CD-RW/DVD-ROM"
+#~ msgstr "CD-RV/DVD-ROM"
+
+#~ msgid "CD-RW/DVD-RAM"
+#~ msgstr "CD-RV/DVD-RAM"
+
+#~ msgid "CD-RW/DVD-R"
+#~ msgstr "CD-RV/DVD-R"
+
+#~ msgid "CD-RW/DVD-RW"
+#~ msgstr "CD-RV/DVD-RV"
+
+#~ msgid "IEEE1394 Drive"
+#~ msgstr "IEEE1394 disk"
+
+#~ msgid "CF"
+#~ msgstr "CF"
+
+#~ msgid "SD/MMC"
+#~ msgstr "SD/MMC"
+
+# Čarobni štapić? :)
+#~ msgid "Memory Stick"
+#~ msgstr "Memorijski štapić"
+
+#~ msgid "Root Volume"
+#~ msgstr "Koreni disk"
+
+#~ msgid "Audio CD"
+#~ msgstr "Muzički disk"
+
+#~ msgid "Unknown volume"
+#~ msgstr "Nepoznati disk"
+
+#~ msgid "Network server"
+#~ msgstr "Mrežni server"
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. There is probably no floppy in the "
+#~ "drive."
+#~ msgstr "Ne mogu da priključim disketu. Verovatno disketa nije u uređaju. "
+
+#~ msgid ""
+#~ "Unable to mount the volume. There is probably no media in the device."
+#~ msgstr "Ne mogu da priključim disk. Verovatno nema nosača u uređaju. "
+
+#~ msgid ""
+#~ "Unable to mount the floppy drive. The floppy is probably in a format that "
+#~ "cannot be mounted."
+#~ msgstr ""
+#~ "Ne mogu da priključim disketu. Verovatno je disketa u zapisu koji se ne "
+#~ "može čitati."
+
+#~ msgid ""
+#~ "Unable to mount the volume. If this is an encrypted drive, then the wrong "
+#~ "password or key was used."
+#~ msgstr ""
+#~ "Ne mogu da priključim disk. Ako je on šifrovan, tada je bila iskorišćena "
+#~ "pogrešna lozinka ili ključ."
+
+#~ msgid ""
+#~ "Unable to mount the selected volume. The volume is probably in a format "
+#~ "that cannot be mounted."
+#~ msgstr ""
+#~ "Ne mogu da priključim izabrani disk. Verovatno je disk u zapisu koji se ne "
+#~ "može čitati."
+
+#~ msgid "Unable to mount the selected floppy drive."
+#~ msgstr "Ne mogu da priključim izabranu disketu."
+
+#~ msgid "Unable to mount the selected volume."
+#~ msgstr "Ne mogu da priključim izabrani disk."
+
+#~ msgid ""
+#~ "Unable to unmount the selected volume. The volume is in use by one or "
+#~ "more programs."
+#~ msgstr ""
+#~ "Ne mogu da odspojim izabrani disk. Njega verovatno koristi neki program "
+#~ "ili programi."
+
+#~ msgid "Unable to unmount the selected volume."
+#~ msgstr "Ne mogu da odspojim izabrani disk."
+
+#~ msgid "Failed to read data from child process %d (%s)"
+#~ msgstr "Neuspešno čitanje datoteke iz naslednog procesa %d (%s)"
+
+#~ msgid "Couldn't run mount process in a pty"
+#~ msgstr "Ne mogu da pokrenem proces priključenja u lažnom terminalu"
+
+#~ msgid "Unexpected error in select() reading data from a child process (%s)"
+#~ msgstr ""
+#~ "Neočekivana greška u funkciji select() pri čitanju podataka u naslednom "
+#~ "procesu (%s)"
+
+#~ msgid "Unexpected error in waitpid() (%s)"
+#~ msgstr "Neočekivana greška unutar izvršenja funkcije waitpid() (%s)"
+
+#~ msgid "Unable to eject media"
+#~ msgstr "Ne mogu da izbacim nosač"
+
+#~ msgid "Home"
+#~ msgstr "Lični"
+
+#~ msgid "Unknown GnomeVFSSeekPosition %d"
+#~ msgstr "Nepoznato GnomeVFSSeekPosition %d"
+
+#~ msgid "The identity of the remote computer (%s) is unknown."
+#~ msgstr "Identitet udaljenog računara (%s) nije poznat."
+
+#~ msgid "Didn't find a valid settings file at %s\n"
+#~ msgstr "Nisam našao ispravnu datoteku sa podešavanjima u %s\n"
+
+#~ msgid "Use the %s environment variable to specify a different location.\n"
+#~ msgstr "Koristite promenljivu okruženja %s da naznačite drugu putanju.\n"
+
+#~ msgid "Your HTTP Proxy requires you to log in.\n"
+#~ msgstr "Vaš HTTP posrednik zahteva prijavu.\n"
+
+#~ msgid ""
+#~ "You must log in to access \"%s\".\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Morate se prijaviti kako biste pristupili „%s“.\n"
+#~ "%s"
+
+#~ msgid "Your password will be transmitted unencrypted."
+#~ msgstr "Lozinka će biti preneta nezaštićena."
+
+#~ msgid "Your password will be transmitted encrypted."
+#~ msgstr "Lozinka će biti šifrovana pre prenosa."
+
+#~ msgid "You must log in to access %s domain %s\n"
+#~ msgstr "Morate se prijaviti kako biste pristupili %s, domen %s\n"
+
+#~ msgid "You must log in to access %s\n"
+#~ msgstr "Morate se prijaviti kako biste pristupili %s\n"
+
+#~ msgid "Default component viewer application"
+#~ msgstr "Podrazumevani program za pregled delova"
+
+#~ msgid "Default terminal application"
+#~ msgstr "Podrazumevani terminalski program"
+
+# bug: no slang, s/exec/execut.../?
+#~ msgid "Exec argument for default terminal"
+#~ msgstr "Argument izvršavanja za podrazumevani terminal"
+
+#~ msgid ""
+#~ "The application to use for viewing files that require a component to view "
+#~ "them. The parameter %s will be replaced by the file's URIs, the parameter "
+#~ "%c will be replaced by the component IID."
+#~ msgstr ""
+#~ "Program koji se koristi za pregledanje datoteka koje zahtevaju komponentu "
+#~ "za pregled. Parametar %s će biti zamenjen adresom datoteke, a parametar %c "
+#~ "će biti zamenjen IID-om komponente."
+
+#~ msgid ""
+#~ "The default terminal application to use for applications that require a "
+#~ "terminal."
+#~ msgstr ""
+#~ "Podrazumevani terminalski program koji se koristi za programe kojima je "
+#~ "neophodan terminal."
+
+# bug: no slang, s/exec/execute.../?
+#~ msgid "The exec argument to use for the default terminal application."
+#~ msgstr "Argument izvršavanja za podrazumevani terminalski program."
+
+#~ msgid "Run the command in a terminal"
+#~ msgstr "Pokreni naredbu u terminalu"
+
+#~ msgid "The command used to handle \"aim\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „aim“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"callto\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „callto“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"ghelp\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „ghelp“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"h323\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „h323“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"http\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „http“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"https\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „https“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"info\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „info“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"mailto\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „mailto“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"man\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „man“ adresama, ako je uključeno."
+
+#~ msgid "The command used to handle \"trash\" URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „trash“ adresama, ako je uključeno."
+
+#~ msgid "The handler for \"aim\" URLs"
+#~ msgstr "Rukovaoc „aim“ adresama"
+
+#~ msgid "The handler for \"callto\" URLs"
+#~ msgstr "Rukovaoc „callto“ adresama"
+
+#~ msgid "The handler for \"ghelp\" URLs"
+#~ msgstr "Rukovaoc „ghelp“ adresama"
+
+#~ msgid "The handler for \"h323\" URLs"
+#~ msgstr "Rukovaoc „h323“ adresama"
+
+#~ msgid "The handler for \"http\" URLs"
+#~ msgstr "Rukovaoc „http“ adresama"
+
+#~ msgid "The handler for \"https\" URLs"
+#~ msgstr "Rukovaoc „https“ adresama"
+
+#~ msgid "The handler for \"info\" URLs"
+#~ msgstr "Rukovaoc „info“ adresama"
+
+#~ msgid "The handler for \"mailto\" URLs"
+#~ msgstr "Rukovaoc „mailto“ adresama"
+
+#~ msgid "The handler for \"man\" URLs"
+#~ msgstr "Rukovaoc „man“ adresama"
+
+#~ msgid "The handler for \"trash\" URLs"
+#~ msgstr "Rukovaoc „trash“ adresama"
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"aim"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„aim“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"callto\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„callto“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"ghelp"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„ghelp“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"h323"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„h323“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"http"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„http“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"https"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„https“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"info"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„info“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle "
+#~ "\"mailto\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„mailto“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"man"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„man“ adrese."
+
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle \"trash"
+#~ "\" URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„trash“ adrese."
+
+#~ msgid ""
+#~ "True if the command used to handle this type of URL should be run in a "
+#~ "terminal."
+#~ msgstr ""
+#~ "Uključeno ako naredba koja se koristi za ove adrese treba da se pokreće u "
+#~ "terminalu."
+
+#~ msgid "Whether the specified command should handle \"aim\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „aim“ adrese."
+
+#~ msgid "Whether the specified command should handle \"callto\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „callto“ adrese."
+
+#~ msgid "Whether the specified command should handle \"ghelp\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „ghelp“ adrese."
+
+#~ msgid "Whether the specified command should handle \"h323\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „h323“ adrese."
+
+#~ msgid "Whether the specified command should handle \"http\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „http“ adrese."
+
+#~ msgid "Whether the specified command should handle \"https\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „https“ adrese."
+
+#~ msgid "Whether the specified command should handle \"info\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „info“ adrese."
+
+#~ msgid "Whether the specified command should handle \"mailto\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „mailto“ adrese."
+
+#~ msgid "Whether the specified command should handle \"man\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „man“ adrese."
+
+#~ msgid "Whether the specified command should handle \"trash\" URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „trash“ adrese."
+
+#~ msgid ""
+#~ "Comma separated list of DNS-SD domains that should be visible in the "
+#~ "\"network:///\" location."
+#~ msgstr ""
+#~ "Zapetom razdvojen spisak DNS-SD domena koji su dostupni na putanji "
+#~ "„network:///."
+
+#~ msgid "Extra domains to look for DNS-SD services in"
+#~ msgstr "Dopunski domeni na kojima da traži DNS-SD usluge"
+
+#~ msgid "How to display local DNS-SD service"
+#~ msgstr "Kako da prikazuje lokalnu DNS-SD uslugu"
+
+#~ msgid "Possible values are \"merged\", \"separate\" and \"disabled\"."
+#~ msgstr ""
+#~ "Dopuštene vrednosti su „merged“ (spojeno), „separate“ (razdvojeno) i "
+#~ "„disabled“ (isključeno)."
+
+#~ msgid "Authenticate proxy server connections"
+#~ msgstr "Identifikuj veze sa posredničkim serverom"
+
+#~ msgid "Automatic proxy configuration URL"
+#~ msgstr "Adresa za samopodešavanje posrednika"
+
+#~ msgid "Enables the proxy settings when accessing HTTP over the Internet."
+#~ msgstr "Uključuje podešavanja posrednika pri pristupu vebu preko Interneta."
+
+#~ msgid "FTP proxy host name"
+#~ msgstr "Ime FTP posrednika"
+
+#~ msgid "FTP proxy port"
+#~ msgstr "Port FTP posrednika"
+
+#~ msgid "HTTP proxy host name"
+#~ msgstr "Ime HTTP posrednika"
+
+#~ msgid "HTTP proxy port"
+#~ msgstr "Port HTTP posrednika"
+
+#~ msgid "HTTP proxy username"
+#~ msgstr "Korisnik HTTP posrednika"
+
+#~ msgid ""
+#~ "If true, then connections to the proxy server require authentication. The "
+#~ "username/password combo is defined by \"/system/http_proxy/"
+#~ "authentication_user\" and \"/system/http_proxy/authentication_password\"."
+#~ msgstr ""
+#~ "Ukoliko je postavljeno, veze sa posredničkim serverom se identifikuju. Par "
+#~ "korisnik/lozinka se uzima iz „/system/http_proxy/authentication_user“ i „/"
+#~ "system/http_proxy/authentication_password“."
+
+#~ msgid "Non-proxy hosts"
+#~ msgstr "Besposredničke adrese"
+
+#~ msgid "Password to pass as authentication when doing HTTP proxying."
+#~ msgstr "Lozinka koja se koristi za identifikaciju kod veb posrednika."
+
+#~ msgid "Proxy configuration mode"
+#~ msgstr "Način podešavanja posrednika"
+
+#~ msgid "SOCKS proxy host name"
+#~ msgstr "Ime SOCKS posrednika"
+
+#~ msgid "SOCKS proxy port"
+#~ msgstr "Port SOCKS posrednika"
+
+#~ msgid "Secure HTTP proxy host name"
+#~ msgstr "Ime bezbednog HTTP posrednika"
+
+#~ msgid "Secure HTTP proxy port"
+#~ msgstr "Port bezbednog HTTP posrednika"
+
+#~ msgid ""
+#~ "Select the proxy configuration mode. Supported values are \"none\", "
+#~ "\"manual\", \"auto\"."
+#~ msgstr ""
+#~ "Izaberite režim podešavanja posrednika. Dopuštene vrednosti su „none“, "
+#~ "„manual“ i „auto“."
+
+#~ msgid "The machine name to proxy FTP through."
+#~ msgstr "Ime računara za FTP posredovanje."
+
+#~ msgid "The machine name to proxy HTTP through."
+#~ msgstr "Ime računara za veb (HTTP) posredovanje."
+
+#~ msgid "The machine name to proxy secure HTTP through."
+#~ msgstr "Ime računara za bezbedno veb (HTTPS) posredovanje."
+
+# bug: s/socks/SOCKS/
+#~ msgid "The machine name to proxy socks through."
+#~ msgstr "Ime računara za SOCKS posredovanje."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/http_proxy/host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port računara datog u „/system/http_proxy/host“ kroz koji posreduje."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/ftp_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port računara datog u „/system/proxy/ftp_proxy“ kroz koji posreduje."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/secure_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port računara datog u „/system/proxy/secure_proxy“ kroz koji posreduje."
+
+#~ msgid ""
+#~ "The port on the machine defined by \"/system/proxy/socks_host\" that you "
+#~ "proxy through."
+#~ msgstr ""
+#~ "Port mašine određene pomoću „/system/proxy/socks_proxy“ koja je posrednik."
+
+#~ msgid ""
+#~ "This key contains a list of hosts which are connected to directly, rather "
+#~ "than via the proxy (if it is active). The values can be hostnames, "
+#~ "domains (using an initial wildcard like *.foo.com), IP host addresses "
+#~ "(both IPv4 and IPv6) and network addresses with a netmask (something like "
+#~ "192.168.0.0/24)."
+#~ msgstr ""
+#~ "Ovaj ključ sadrži spisak računara koji su neposredno povezani, umesto "
+#~ "putem posrednika (ukoliko je u dejstvu). Ove vrednosti mogu biti imena "
+#~ "računara, domeni (pomoću početnih navoda kao što je *.nešto.iju), IP "
+#~ "adrese računara (bilo IP4 bilo IP6) i adrese mreža uz mrežnu masku (nešto "
+#~ "kao što je 192.168.0.0/24)."
+
+#~ msgid "URL that provides proxy configuration values."
+#~ msgstr "Adresa koja obezbeđuje vrednosti za podešavanje posrednika."
+
+#~ msgid "Use HTTP proxy"
+#~ msgstr "Koristi veb posrednika"
+
+#~ msgid "User name to pass as authentication when doing HTTP proxying."
+#~ msgstr "Korisničko ime koje se šalje pri identifikaciji kod veb posrednika."
+
+#~ msgid "SMB workgroup"
+#~ msgstr "SMB radna grupa"
+
+#~ msgid ""
+#~ "The Windows networking workgroup or domain that the user is part of. In "
+#~ "order for a new workgroup to fully take effect the user may need to log "
+#~ "out and log back in."
+#~ msgstr ""
+#~ "Radna grupa ili domen Windows mreže čiji je korisnik član. Da bi nova "
+#~ "radna grupa uzela maha korisnik će možda morati da se odjavi i ponovo "
+#~ "prijavi."
+
+# Gnomov Virtuelni Sistem Datoteka — VSD? Ili Gnomovo „oponašanje sistema datoteka“ — OSD?
+#~ msgid "Could not initialize gnome vfs"
+#~ msgstr "Ne mogu da pokrenem Gnomovo oponašanje sistema datoteka"
+
+#~ msgid "Standard Moniker factory"
+#~ msgstr "Proizvodnja običnog nadimka"
+
+#~ msgid "file MonikerExtender"
+#~ msgstr "datoteka MonikerExtender"
+
+#~ msgid "generic Gnome VFS moniker"
+#~ msgstr "osnovni nadimak Gnomovog oponašavača sistema datoteka"
+
+#~ msgid "generic file moniker"
+#~ msgstr "osnovni nadimak datoteke"
+
+#~ msgid "Display SCSI drives"
+#~ msgstr "Prikaži SCSI uređaje"
+
+#~ msgid "Display SCSI optical drives"
+#~ msgstr "Prikaži optičke SCSI uređaje"
+
+#~ msgid "Display drives with removable media"
+#~ msgstr "Prikaži uređaje sa uklonjivim nosačima"
+
+#~ msgid "Display external drives"
+#~ msgstr "Prikaži spoljašnje uređaje"
+
+#~ msgid "Display internal hard drives"
+#~ msgstr "Prikaži unutrašnje tvrde diskove"
+
+#~ msgid ""
+#~ "Whether to display SCSI optical drives even if /system/storage/"
+#~ "display_scsi_drives is set to FALSE."
+#~ msgstr ""
+#~ "Da li da prikazuje optičke SCSI uređaje čak i ako je /system/storage/"
+#~ "display_scsi_drives isključen."
+
+#~ msgid "Whether to display drives and mountable volumes from SCSI drives."
+#~ msgstr "Da li da prikazuje uređaje i priključive diskove sa SCSI uređaja."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from drives with "
+#~ "removable media (e.g. drives where media can be inserted and removed)."
+#~ msgstr ""
+#~ "Da li da prikazuje uređaje i priključive diskove sa uređaja sa uklonjivim "
+#~ "nosačima (npr. uređaji gde se nosač može ubaciti i izbaciti)."
+
+# bug: hotpluggable is technobabble, second part of "eg." should be enough
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from external drives (e."
+#~ "g. drives that are hotpluggable; e.g. drives that can be attached and "
+#~ "detached while the system is running)."
+#~ msgstr ""
+#~ "Da li da prikazuje uređaje i priključive diskove sa spoljašnjih uređaja "
+#~ "(npr. uređaji koji se mogu priključiti u toku rada)."
+
+#~ msgid ""
+#~ "Whether to display drives and mountable volumes from internal hard drives "
+#~ "(non-SCSI optical drives are always shown)."
+#~ msgstr ""
+#~ "Da li da prikazuje uređaje i priključive diskove sa unutrašnjih tvrdih "
+#~ "diskova (otpički ne-SCSI diskovi se uvek prikazuju)."
+
+#~ msgid "The window workgroup the user is part of"
+#~ msgstr "Vindouz radna grupa koje je korisnik član"
+
+#~ msgid "Optical Disc"
+#~ msgstr "Optički disk"
+
+# Čarobni štapić? :)
+#~ msgid "Memory Stick Media"
+#~ msgstr "Memorijski štapić (MS)"
+
+#~ msgid "Smart Media Media"
+#~ msgstr "Mudri nosač (SM)"
+
+#~ msgid "Mac OS disk"
+#~ msgstr "Mekintoš disk"
+
+#~ msgid "Mac OS X disk"
+#~ msgstr "Mekintoš OS-Iks disk"
+
+# Transkripcija na nivou ;-)
+#~ msgid "Windows Disk"
+#~ msgstr "Vinduz disk"
+
+#~ msgid "Linux Disk"
+#~ msgstr "Linuks disk"
+
+#~ msgid "File could not be opened: %s"
+#~ msgstr "Datoteka se ne može otvoriti: %s"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain line '%s' which is not an entry, group, or comment"
+#~ msgstr ""
+#~ "„.desktop“ datoteka sadrži red „%s“ koji nije unos, grupa ni primedba"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries file does not start with legal start group"
+#~ msgstr "„.desktop“ datoteka ne počinje sa ispravnom početnom grupom"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain line '%s' which is not UTF-8"
+#~ msgstr "„.desktop“ datoteka sadrži red „%s“ koji nije UTF-8"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain unknown encoding '%s'"
+#~ msgstr "„.desktop“ datoteka koristi nepoznato kodiranje „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries do not have group '%s'"
+#~ msgstr "„.desktop“ datoteka nema grupu „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries do not have key '%s'"
+#~ msgstr "„.desktop“ datoteka nema ključ „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain key '%s' which has value that cannot be "
+#~ "interpreted."
+#~ msgstr ""
+#~ "„.desktop“ datoteka sadrži ključ „%s“ koji ima vrednost koja se ne može "
+#~ "razumeti."
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid ""
+#~ "desktop entries contain no translated value for key '%s' with locale '%s'."
+#~ msgstr ""
+#~ "„.desktop“ datoteka ne sadrži prevod vrednosti ključa „%s“ u lokalitetu „%"
+#~ "s“."
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain invalid escape sequence '%s'"
+#~ msgstr "„.desktop“ datoteka sadrži neispravan znak za isticanje „%s“"
+
+# bug: "desktop entries" sucks pretty much (it could be "entries in .desktop file")
+#~ msgid "desktop entries contain escape character at end of line"
+#~ msgstr ""
+#~ "„.desktop“ datoteka sadrži neispravan znak za isticanje na kraju reda"
+
+#~ msgid "Value '%s' cannot be interpreted as a number."
+#~ msgstr "Vrednost „%s“ se ne može posmatrati kao broj."
+
+#~ msgid "Value '%s' cannot be interpreted as a boolean."
+#~ msgstr "Vrednost „%s“ se ne može posmatrati kao istinitosna vrednost."
+
+#~ msgid "Applications"
+#~ msgstr "Programi"
+
+#~ msgid "Cards"
+#~ msgstr "Karte"
+
+#~ msgid "Folders"
+#~ msgstr "Fascikle"
+
+#~ msgid "Help"
+#~ msgstr "Pomoć"
+
+#~ msgid "Hosts"
+#~ msgstr "Računari"
+
+#~ msgid "Links"
+#~ msgstr "Veze"
+
+#~ msgid "Mail"
+#~ msgstr "Pošta"
+
+#~ msgid "Tools"
+#~ msgstr "Alati"
+
+#~ msgid "Windows"
+#~ msgstr "Prozori"
+
+# bug: inconsistent with other strings which use "...to handle \"h323\" URLs..."
+#~ msgid "The command used to handle HTTP URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „http“ adresama, ako je uključeno."
+
+# bug: inconsistent with other strings which use "...to handle \"h323\" URLs..."
+#~ msgid "The command used to handle HTTPS URLs, if enabled."
+#~ msgstr "Naredba korišćena za baratanje „https“ adresama, ako je uključeno."
+
+# bug: inconsistent with other strings; should be "The handler for \"http\" URLs"
+#~ msgid "The handler for HTTP URLs"
+#~ msgstr "Rukovaoc „http“ adresama"
+
+# bug: inconsistent with other strings; should be "The handler for \"https\" URLs"
+#~ msgid "The handler for HTTPS URLs"
+#~ msgstr "Rukovaoc „https“ adresama"
+
+# bug: inconsistent; should be "...should handle \"http\" URLs."
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle HTTP "
+#~ "URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„http“ adrese."
+
+# bug: inconsistent; should be "...should handle \"https\" URLs."
+#~ msgid ""
+#~ "True if the command specified in the \"command\" key should handle HTTPS "
+#~ "URLs."
+#~ msgstr ""
+#~ "Uključeno ako naredba navedena u ključu „command“ treba da se koristi za "
+#~ "„https“ adrese."
+
+# bug: inconsistent; should be "...should handle \"http\" URLs".
+#~ msgid "Whether the specified command should handle HTTP URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „http“ adrese."
+
+# bug: inconsistent; should be "...should handle \"https\" URLs".
+#~ msgid "Whether the specified command should handle HTTPS URLs"
+#~ msgstr "Da li navedena naredba treba da se koristi za „https“ adrese."
+
+#~ msgid "H323 URL handler"
+#~ msgstr "Rukovalac H323 adresama"
+
+#~ msgid "HTTP URL handler"
+#~ msgstr "Rukovalac HTTP adresama"
+
+#~ msgid "HTTPS URL handler"
+#~ msgstr "Rukovalac HTTPS adresama"
+
+#~ msgid "Handle callto URLs"
+#~ msgstr "Barataj callto adresama"
+
+#~ msgid "Handle ghelp URLs"
+#~ msgstr "Barataj ghelp adresama"
+
+#~ msgid "Handle info URLs"
+#~ msgstr "Barataj info adresama"
+
+#~ msgid "Handle mailto URLs"
+#~ msgstr "Barataj mailto adresama"
+
+#~ msgid "Handle man URLs"
+#~ msgstr "Barataj man adresama"
+
+#~ msgid "callto URL handler"
+#~ msgstr "Rukovalac callto adresama"
+
+#~ msgid "ghelp URL handler"
+#~ msgstr "Rukovalac ghelp adresama"
+
+#~ msgid "info URL handler"
+#~ msgstr "Rukovalac info adresama"
+
+#~ msgid "mailto URL handler"
+#~ msgstr "Rukovalac mailto adresama"
+
+#~ msgid "man URL handler"
+#~ msgstr "Rukovalac man adresama"
+
+#~ msgid "trash URL handler"
+#~ msgstr "Rukovalac trash adresama"
+
+#~ msgid "Could not get information for file '%s': %s"
+#~ msgstr "Ne mogu da saznam podatke o datoteci „%s“: %s"
+
+# bug: as above [inconsistent wording]
+#~ msgid ""
+#~ "Failed to load image '%s': reason not known, probably a corrupt image file"
+#~ msgstr ""
+#~ "Neuspešno učitavanje slike „%s“: razlog nepoznat, verovatno oštećena "
+#~ "datoteka slike"
+
+#~ msgid "How to handle http URLs"
+#~ msgstr "Kako baratati http adresama"
+
+#~ msgid "How to handle https URLs"
+#~ msgstr "Kako baratati https adresama"
+
+#~ msgid "Set to true to have a program specified in command handle https URLs"
+#~ msgstr ""
+#~ "Uključite ako želite da program naveden u naredbi barata https adresama"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/ghelp handle ghelp "
+#~ "URLs"
+#~ msgstr ""
+#~ "Uključite ako želite da program naveden u programs/ghelp barata ghelp "
+#~ "adresama"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/info handle info URLs"
+#~ msgstr ""
+#~ "Uključite ako želite da program naveden u programs/info barata info "
+#~ "adresama"
+
+#~ msgid ""
+#~ "Set to true to have a program specified in programs/man handle man URLs"
+#~ msgstr ""
+#~ "Uključite ako želite da program naveden u programs/man barata man adresama"
+
+#~ msgid "URL handler for h323 uris"
+#~ msgstr "Rukovaoc h323 adresama"
+
+#~ msgid "URL handler for http uris"
+#~ msgstr "Rukovaoc http adresama"
+
+#~ msgid "URL handler for https uris"
+#~ msgstr "Rukovaoc https adresama"
+
+#~ msgid "Hosts are not contacted via the proxy"
+#~ msgstr "Računarima se ne pristupa preko posrednika"
+
+#~ msgid "The machine name to proxy http through."
+#~ msgstr "Ime računara HTTP posrednika."
+
+#~ msgid "Use proxy settings when accessing http"
+#~ msgstr "Koristi podešavanja posrednika pri pristupu vebu"
+
+#~ msgid "http proxy username"
+#~ msgstr "Korisničko ime HTTP posrednika"
+
+# bug: plural-forms
+#~ msgid "1 byte"
+#~ msgstr "1 bajt"
diff --git a/trunk/po/sv.po b/trunk/po/sv.po
new file mode 100644
index 00000000..c337f599
--- /dev/null
+++ b/trunk/po/sv.po
@@ -0,0 +1,2116 @@
+# Swedish messages for gvfs.
+# Copyright (C) 2006-2009 Free Software Foundation, Inc.
+# Christian Rose <menthos@menthos.com>, 2006.
+# Daniel Nylander <po@danielnylander.se>, 2006, 2007, 2008, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-11 12:52+0100\n"
+"PO-Revision-Date: 2009-02-11 12:53+0100\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Åtgärden stöds inte, filer på olika monteringar"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Ogiltigt svarsvärde från get_info"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Ogiltigt svarsvärde från query_info"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Kunde inte få filhandtag för ström"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Ogiltigt svarsvärde från open"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Fick inget filhandtag för ström"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Ogiltigt svarsvärde från call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Ogiltigt svarsvärde från get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Kunde inte hitta inneslutade mount"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Ogiltigt filnamn %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Ogiltigt svarsvärde från query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Ogiltigt svarsvärde från monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Ogiltigt svarsvärde från monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Åtgärden avbröts"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Fel i strömningsprotokoll: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Slut på ström"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Sökning stöds inte i strömmen"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Frågeåtgärden stöds inte"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Informationsbegäran stöds inte i strömmen"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Fel vid hämtning av monteringsinformation: %s"
+
+#: ../client/gvfsdaemondbus.c:568
+#: ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Fel vid anslutning till demon: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Ogiltigt svarsvärde från open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Fel vid skapande av uttag: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Fel vid anslutning till uttag: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Ogiltigt format på filinformation"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Ogiltigt innehåll för attributinformation"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Fel vid initiering av Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Fel vid skapande av Avahi-uppslag: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Fel vid uppslag av \"%s\"-tjänst \"%s\" på domänen \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "Fel vid uppslag av \"%s\"-tjänst \"%s\" på domänen \"%s\". EN eller flera TXT-poster saknas. Nycklar krävs: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Tidsgräns uppnådess vid uppslag av \"%s\"-tjänst \"%s\" på domänen \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Felformulerad dns-sd encoded_triple \"%s\""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Kan inte hantera version %d av GVfsIcon-kodning"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Felformaterat inmatningsdata för GVfsIcon"
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Fel vid anslutning till D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Filsystemstjänst för %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Fel: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Användning: %s --spawner dbus-id objektsökväg"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Användning: %s nyckel=värde nyckel=värde ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Ingen monteringstyp angiven"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "monteringspunkt för %s körs redan"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "fel vid start av monteringsdemon"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ på %s"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Inget värdnamn angivet"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836
+#: ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Ogiltig monteringsspecifikation"
+
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262
+#: ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Filen finns inte"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Filen är inte en katalog"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Bränn"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Kunde inte skapa temporärkatalog"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Ingen sådan fil eller katalog"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Katalogen är inte tom"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Kan inte kopiera fil över katalog"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Cd/dvd-skapare"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Filen finns"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Åtgärden stöds inte av bakänden"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Ingen sådan fil eller katalog i målsökväg"
+
+#: ../daemon/gvfsbackendburn.c:877
+#: ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Kan inte kopiera katalog över katalog"
+
+#: ../daemon/gvfsbackendburn.c:886
+#: ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Målfilen finns"
+
+#: ../daemon/gvfsbackendburn.c:893
+#: ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Kan inte kopiera katalog rekursivt"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281
+#: ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587
+#: ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Stöds inte"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Kan inte ansluta till systembussen"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Kan inte skapa libhal-kontext"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Kan inte initiera libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Ingen enhet angiven"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Kan inte hitta enheten %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Enheten %s innehåller inga ljudfiler"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda-montering på %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Ljudskiva"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Filsystemet är upptaget: %d öppnad fil"
+msgstr[1] "Filsystemet är upptaget: %d öppnade filer"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Ingen sådan fil %s på enheten %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Fel från \"paranoia\" på enheten %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Fel vid sökning i ström på enheten %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Ingen sådan fil"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Filen finns inte eller är inte ett ljudspår"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Filsystemstjänst för ljud-cd"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Dator"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Filsystem"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Kan inte öppna katalog"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Kan inte öppna monteringsbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Internt fel: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Kan inte montera fil"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Inget media i enheten"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Inte en monteringsbar fil"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Kan inte avmontera fil"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Kan inte mata ut fil"
+
+#: ../daemon/gvfsbackenddav.c:526
+#: ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP-fel: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Kunde inte tolka svaret"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Tomt svar"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Oväntat svar från server"
+
+#: ../daemon/gvfsbackenddav.c:1179
+#: ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Svaret är ogiltigt"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV-utdelning"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Ange lösenord för %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Ange lösenord för proxyserver"
+
+#: ../daemon/gvfsbackenddav.c:1662
+#: ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Inte en WebDAV-aktiverad utdelning"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV på %s"
+
+#: ../daemon/gvfsbackenddav.c:1754
+#: ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Kunde inte skapa begäran"
+
+#: ../daemon/gvfsbackenddav.c:1890
+#: ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254
+#: ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Målfilen finns redan"
+
+#: ../daemon/gvfsbackenddav.c:1963
+#: ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Filen blev externt ändrad"
+
+#: ../daemon/gvfsbackenddav.c:1994
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Skapandet av säkerhetskopia misslyckades"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492
+#: ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Lokalt nätverk"
+
+#: ../daemon/gvfsbackenddnssd.c:736
+#: ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Kan inte övervaka fil eller katalog."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755
+#: ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882
+#: ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Nätverk"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Konton stöds inte"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Värden stängde anslutningen"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Kan inte öppna dataanslutning. Kanske förhindrar din brandvägg detta?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Dataanslutning stängd"
+
+#: ../daemon/gvfsbackendftp.c:271
+#: ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Åtgärden misslyckades"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Inget ledigt utrymme på servern"
+
+#: ../daemon/gvfsbackendftp.c:288
+#: ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Åtgärden stöds inte"
+
+#: ../daemon/gvfsbackendftp.c:292
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Åtkomst nekas"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Sidtypen är okänd"
+
+#: ../daemon/gvfsbackendftp.c:300
+#: ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Ogiltigt filnamn"
+
+#: ../daemon/gvfsbackendftp.c:304
+#: ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Ogiltigt svar"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "avbruten överföring"
+
+#: ../daemon/gvfsbackendftp.c:710
+#: ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Kunde inte ansluta till värd"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "Ange lösenordet för ftp som %s på %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Ange lösenord för ftp på %s"
+
+#: ../daemon/gvfsbackendftp.c:1523
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Lösenordsdialogen avbröts"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp på %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp som %s på %s"
+
+#: ../daemon/gvfsbackendftp.c:1690
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Filen är en katalog"
+
+#: ../daemon/gvfsbackendftp.c:1912
+#: ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "säkerhetskopior stöds inte än"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "filnamnet är för långt"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Ogiltigt målfilnamn"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Katalog eller fil finns redan"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Ingen sådan fil eller katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Ogiltigt filnamn"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Stöds inte"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Digitalkamera (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823
+#: ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s-kamera"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826
+#: ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s-ljudspelare"
+
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:837
+#: ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Ljudspelare"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Ingen enhet angiven"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Kan inte skapa gphoto2-kontext"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Fel vid skapande av kamera"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383
+#: ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Fel vid inläsning av enhetsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Fel vid uppslag av enhetsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Fel vid hämtning av enhetsinformation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Fel vid konfiguration av port för kamerakommunikation"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Fel vid initiering av kamera"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2-montering på %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Ingen kamera angiven"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Fel vid skapande av filobjekt"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Fel vid hämtning av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Fel vid datahämtning från fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Felformaterad ikonidentifierare \"%s\""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772
+#: ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Fel vid sökning i ström på kameran %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Inte en katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Misslyckades med att få tag på mapplista"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Misslyckades med att få tag på fillista"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Fel vid skapande av katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Namnet finns redan"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513
+#: ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Nytt namn är för långt"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Fel vid namnbyte av katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Fel vid namnbyte av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Katalogen \"%s\" är inte tom"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Fel vid borttagning av katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Fel vid borttagning av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Kan inte skriva till katalog"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Kan inte allokera ny fil att lägga till i"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Kan inte läsa fil att lägga till i"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Kan inte få tag på data för fil att lägga till i"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Fel vid skrivning av fil"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Stöds inte (inte samma katalog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Stöds inte (källa är katalog, mål är katalog)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Stöds inte (källa är katalog, mål är befintlig fil)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Stöds inte (källa är fil, mål är katalog)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP-klientfel: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (ogiltig kodning)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Notifiering för katalog stöds inte"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows-nätverk"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Övervakare för nätverksplatser"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s på %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB-stöd saknas. Kontakta din programtillverkare"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Anslutning till enheten förlorades"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Enheten kräver en programuppdatering"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh-programmet avslutades oväntat"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Värdnamnet är inte känt"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Ingen väg till värd"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Anslutningen nekades av server"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Verifiering av värdnyckel misslyckades"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Kunde inte starta ssh-program"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Kunde inte starta ssh-program: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Tidsgräns överstigen vid inloggning"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Ange lösenfras för nyckel"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Ange lösenord"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Kan inte skicka lösenord"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Logga in ändå"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Avbryt inloggning"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Identiteten för fjärrdatorn (%s) är inte känd.\n"
+"Det här händer när du loggar in på en dator för första gången.\n"
+"\n"
+"Identiteten som skickades av fjärrdatorn är %s. Du bör kontakta systemadministratören om du vill vara absolut säker på identiteten."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Inloggningsdialogen avbröts"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Kan inte skicka värdidentitetsbekräftelse"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokollfel"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp för %s på %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp på %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Kunde inte hitta ssh-kommando som stöds"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Fel"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721
+#: ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898
+#: ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010
+#: ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348
+#: ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512
+#: ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648
+#: ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736
+#: ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785
+#: ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Ogiltigt svar togs emot"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "Ogiltigt icon_id \"%s\" i OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Fel vid skapande av säkerhetskopia: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Kunde inte skapa temporärfil"
+
+#: ../daemon/gvfsbackendsftp.c:3574
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Kan inte flytta katalog över katalog"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Lösenord krävs för utdelningen %s på %s"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Internt fel (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Misslyckades med att montera Windows-utdelning"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Söktypen stöds inte"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Skapandet av säkerhetskopia misslyckades: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Fel vid borttagning av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Fel vid flyttning av fil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Fel vid borttagning av målfil: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Kan inte flytta katalog rekursivt"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Filsystemstjänst för Windows-utdelningar"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "Lösenord krävs för %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows-utdelningar på %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Misslyckades med att hämta utdelningslista från server"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Filen är inte monteringsbar"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Inte en vanlig fil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Filsystemstjänst för Windows-nätverk"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#: ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Papperskorgsmappen kan inte tas bort"
+
+#: ../daemon/gvfsbackendtrash.c:387
+#: ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Objekt i papperskorgen kan inte ändras"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735
+#: ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Papperskorg"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Ogiltig typ av bakände"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Fel vid sändning av fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symboliska länkar stöds inte av bakänden"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Ogiltigt dbus-meddelande"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Ersätt gammal demon."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Starta inte fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS-demon"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Huvuddemon för GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Prova \"%s --help\" för mer information."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Ogiltiga argument från startad barnprocess"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automatisk montering misslyckades: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Angiven plats är inte monterad"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Angiven plats stöds inte"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Platsen är redan monterad"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Platsen är inte monteringsbar"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Cd-romskiva"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Tom cd-rom-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Cd-r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Tom cd-r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Cd-rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Tom cd-rw-skiva"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Dvd-romskiva"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Tom dvd-rom-skiva"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Dvd-ramskiva"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Tom dvd-ramskiva"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Dvd-rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Tom dvd-rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Dvd+r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Tom dvd+r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Dvd+rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Tom dvd+rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Tom DVD+R DL-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Tom Blu-Ray-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Tom Blu-Ray r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Tom Blu-Ray rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD dvd-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Tom HD dvd-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD dvd-r-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Tom HD dvd-rom-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD dvd-rw-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Tom HD dvd-rw-skiva"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Mo-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Tom mo-skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Skiva"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Tom skiva"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "Cd-rom"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "Cd-r"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "Cd-rw"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "Dvd-rom"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "Dvd+r"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "Dvd+rw"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "Dvd-r"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "Dvd-rw"
+
+# http://www.nada.kth.se/dataterm/rek.html#a23
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "Dvd-ram"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "Dvd±r"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "Dvd±rw"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s-enhet"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s-enhet"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Diskettenhet"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Programvaru-RAID-enhet"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB-enhet"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA-enhet"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI-enhet"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire-enhet"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Bandenhet"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash-enhet"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick-enhet"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia-enhet"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC-enhet"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip-enhet"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz-enhet"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Minnespinne"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Masslagringsenhet"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Misslyckades med att mata ut media; en eller flera volymer på mediet är upptagna."
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Blandad ljud- och dataskiva"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s-media"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s-krypterat data"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: fel vid öppning av fil: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, fel vid skrivning till standard ut"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: fel vid läsning: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: fel vid stängning: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "PLATS... - sammanfoga PLATSER till standard ut."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Sammanfoga filer på platser och skriv ut till standard ut. Fungerar precis som det traditionella verktyget cat, men använder gvfs-plats istället för lokala filer: till exempel kan du använda något liknande smb://server/resurs/fil.txt som plats att sammanfoga."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Observera: bara att skicka genom cat om du behöver dess formatflagga som -n, -T eller andra."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: saknar platser"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: fel vid öppnande av plats: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: fel vid start av program: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILER... - öppna FILER med registrerade program."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Öppnar fil(er) med standardprogrammet registrerat att hantera den typen av fil."
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Kan inte ta bort papperskorg"
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (i papperskorg)"
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Notifiering för papperskorgskatalog stöds inte"
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#, fuzzy
+#~ msgid "Error creating port info list"
+#~ msgstr "Fel vid skapande av uttag: %s"
+
+#, fuzzy
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "Fel vid hämtning av monteringsinformation: %s"
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "Filsystemet är upptaget: %d öppnade filer"
+#~ msgid "Error listing folders"
+#~ msgstr "Fel vid mapplistning"
+#~ msgid "Error listing files in folder"
+#~ msgstr "Fel vid fillistning i mapp"
+#~ msgid "File unavailable"
+#~ msgstr "Filen är inte tillgänglig"
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB-media"
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB-media"
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB-media"
+#~ msgid "Invalid reply from server"
+#~ msgstr "Ogiltigt svar från server"
+#~ msgid "File does not exist"
+#~ msgstr "Filen finns inte"
+#~ msgid "Operation cancelled"
+#~ msgstr "Åtgärden avbröts"
+#~ msgid "FTP on %s"
+#~ msgstr "FTP på %s"
+#~ msgid "FTP on %s:%u"
+#~ msgstr "FTP på %s:%u"
+#~ msgid "The file does not exist"
+#~ msgstr "Filen finns inte"
+#~ msgid "Audio Disc on %s"
+#~ msgstr "Ljudskiva på %s"
+#~ msgid "CD Burner"
+#~ msgstr "Cd-brännare"
+#~ msgid "Error connecting dbus: %s\n"
+#~ msgstr "Fel vid anslutning till dbus: %s\n"
+#~ msgid "Can't enumerate non-directory"
+#~ msgstr "Kan inte numrera icke-katalog"
+#~ msgid "Can't find mount for mounted volume"
+#~ msgstr "Kan inte hitta montering för monterad volym"
+#~ msgid "Failed to allocate smb context"
+#~ msgstr "Misslyckades med att allokera smb-kontext"
+#~ msgid "Failed to initialize smb context"
+#~ msgstr "Misslyckades med att initiera smb-kontext"
+#~ msgid ""
+#~ "A list of default mount options for volumes formatted with the iso9660 "
+#~ "file system."
+#~ msgstr ""
+#~ "En lista på standardmonteringsalternativ för volymer som är formaterade "
+#~ "med iso9660-filsystemet."
+#~ msgid ""
+#~ "A list of default mount options for volumes formatted with the ntfs file "
+#~ "system using ntfs-3g."
+#~ msgstr ""
+#~ "En lista på standardmonteringsalternativ för volymer som är formaterade "
+#~ "med ntfs-filsystemet med ntfs-3g."
+#~ msgid ""
+#~ "A list of default mount options for volumes formatted with the ntfs file "
+#~ "system."
+#~ msgstr ""
+#~ "En lista på standardmonteringsalternativ för volymer som är formaterade "
+#~ "med ntfs-filsystemet."
+#~ msgid ""
+#~ "A list of default mount options for volumes formatted with the udf file "
+#~ "system."
+#~ msgstr ""
+#~ "En lista på standardmonteringsalternativ för volymer som är formaterade "
+#~ "med udf-filsystemet."
+#~ msgid ""
+#~ "A list of default mount options for volumes formatted with the vfat file "
+#~ "system."
+#~ msgstr ""
+#~ "En lista på standardmonteringsalternativ för volymer som är formaterade "
+#~ "med vfat-filsystemet."
+#~ msgid "Default mount options for iso9660 fs"
+#~ msgstr "Standardmonteringsalternativ för iso9960-filsystem"
+#~ msgid "Default mount options for ntfs fs"
+#~ msgstr "Standardmonteringsalternativ för ntfs-filsystem"
+#~ msgid "Default mount options for ntfs-3g fs"
+#~ msgstr "Standardmonteringsalternativ för ntfs-3g-filsystem"
+#~ msgid "Default mount options for udf fs"
+#~ msgstr "Standardmonteringsalternativ för udf-filsystem"
+#~ msgid "Default mount options for vfat fs"
+#~ msgstr "Standardmonteringsalternativ för vfat-filsystem"
+#~ msgid ""
+#~ "The name of the file system driver to use by default when 'ntfs' is "
+#~ "detected. This is useful for configuring the system to use the 'ntfs-3g' "
+#~ "driver for all 'ntfs' file systems by default. User can still choose to "
+#~ "use the 'ntfs' file system driver by overriding it per-volume or on the "
+#~ "command line."
+#~ msgstr ""
+#~ "Namnet på filsystemdrivrutinen som ska användas som standard när \"ntfs\" "
+#~ "identifieras. Det här är användbart för konfigurering av systemet till "
+#~ "att använda drivrutinen \"ntfs-3g\" för alla \"ntfs\"-filsystem som "
+#~ "standard. Användaren kan fortfarande välja att använda "
+#~ "filsystemsdrivrutinen \"ntfs\" genom att åsidosätta den för varje volym "
+#~ "eller på kommandoraden."
+#~ msgid "When 'ntfs' is detected, what file system driver to use by default"
+#~ msgstr ""
+#~ "När \"ntfs\" identifieras, vilken filsystemdrivrutin ska användas som "
+#~ "standard"
+#~ msgid "_Username:"
+#~ msgstr "_Användarnamn:"
+#~ msgid "_Domain:"
+#~ msgstr "_Domän:"
+#~ msgid "_Password:"
+#~ msgstr "_Lösenord:"
+#~ msgid "Con_firm password:"
+#~ msgstr "_Bekräfta lösenord:"
+#~ msgid "Password quality:"
+#~ msgstr "Lösenordskvalitet:"
+#~ msgid "Co_nnect"
+#~ msgstr "Ans_lut"
+#~ msgid "Connect _anonymously"
+#~ msgstr "Anslut _anonymt"
+#~ msgid "Connect as u_ser:"
+#~ msgstr "Anslut som an_vändare:"
+#~ msgid "_Forget password immediately"
+#~ msgstr "_Glöm lösenordet omedelbart"
+#~ msgid "_Remember password until you logout"
+#~ msgstr "Kom ihåg lösenordet tills du loggar _ut"
+#~ msgid "_Remember forever"
+#~ msgstr "Kom ihåg _för alltid"
+#~ msgid "You are not privileged to eject the volume '%s'."
+#~ msgstr "Du har inte rättighet att mata ut volymen \"%s\"."
+#~ msgid "You are not privileged to eject this volume."
+#~ msgstr "Du har inte rättighet att mata ut denna volym."
+#~ msgid "An application is preventing the volume '%s' from being ejected."
+#~ msgstr "Ett program förhindrar att volymen \"%s\" kan matas ut."
+#~ msgid "An application is preventing the volume from being ejected."
+#~ msgstr "Ett program förhindrar att volymen kan matas ut."
+#~ msgid "Cannot eject the volume '%s'."
+#~ msgstr "Kan inte mata ut volymen \"%s\"."
+#~ msgid "Cannot eject the volume."
+#~ msgstr "Kan inte mata ut volymen."
+#~ msgid "You are not privileged to unmount the volume '%s'."
+#~ msgstr "Du har inte rättighet att avmontera volymen \"%s\"."
+#~ msgid "You are not privileged to unmount this volume."
+#~ msgstr "Du har inte rättighet att avmontera denna volym."
+#~ msgid "An application is preventing the volume '%s' from being unmounted."
+#~ msgstr "Ett program förhindrar att volymen \"%s\" kan avmonteras."
+#~ msgid "An application is preventing the volume from being unmounted."
+#~ msgstr "Ett program förhindrar att volymen kan avmonteras."
+#~ msgid "The volume '%s' is not mounted."
+#~ msgstr "Volymen \"%s\" är inte monterad."
+#~ msgid "Cannot unmount the volume '%s'."
+#~ msgstr "Kan inte avmontera volymen \"%s\"."
+#~ msgid "Cannot unmount the volume."
+#~ msgstr "Kan inte avmontera volymen."
+#~ msgid "The volume '%s' was probably mounted manually on the command line."
+#~ msgstr "Volymen \"%s\" blev antagligen monterad manuellt på kommandoraden."
+#~ msgid "The volume was probably mounted manually on the command line."
+#~ msgstr "Volymen blev antagligen monterad manuellt på kommandoraden."
+#~ msgid "Error <i>%s</i>."
+#~ msgstr "Fel <i>%s</i>."
+#~ msgid "_Details"
+#~ msgstr "_Detaljer"
+#~ msgid "You are not privileged to mount the volume '%s'."
+#~ msgstr "Du har inte rättighet att montera volymen \"%s\"."
+#~ msgid "You are not privileged to mount this volume."
+#~ msgstr "Du har inte rättighet att montera denna volym."
+#~ msgid "Invalid mount option when attempting to mount the volume '%s'."
+#~ msgstr "Ogiltig monteringsflagg vid försök att montera volymen \"%s\"."
+#~ msgid "Invalid mount option when attempting to mount the volume."
+#~ msgstr "Ogiltig monteringsflagg vid försök att montera volymen."
+#~ msgid ""
+#~ "The volume '%s' uses the <i>%s</i> file system which is not supported by "
+#~ "your system."
+#~ msgstr ""
+#~ "Volymen \"%s\" använder filsystemet <i>%s</i> som inte stöds av ditt "
+#~ "system."
+#~ msgid ""
+#~ "The volume uses the <i>%s</i> file system which is not supported by your "
+#~ "system."
+#~ msgstr ""
+#~ "Volymen använder filsystemet <i>%s</i> som inte stöds av ditt system."
+#~ msgid "Unable to mount the volume."
+#~ msgstr "Kan inte montera volymen."
+#~ msgid "Volume '%s' is already mounted."
+#~ msgstr "Volymen \"%s\" är redan monterad."
+#~ msgid "Mounted %s at \"%s\"\n"
+#~ msgstr "Monterade %s på \"%s\"\n"
+#~ msgid "Device %s is in /etc/fstab with mount point \"%s\"\n"
+#~ msgstr "Enheten %s finns i /etc/fstab med monteringspunkten \"%s\"\n"
+#~ msgid "Mounted %s at \"%s\" (using /etc/fstab)\n"
+#~ msgstr "Monterade %s på \"%s\" (enligt /etc/fstab)\n"
+#~ msgid "Writing data to device"
+#~ msgstr "Skriver data till enhet"
+#~ msgid ""
+#~ "There is data that needs to be written to the device %s before it can be "
+#~ "removed. Please do not remove the media or disconnect the drive."
+#~ msgstr ""
+#~ "Det finns data som behöver skrivas till enheten %s innan den kan kopplas "
+#~ "från. Ta inte bort mediet eller koppla från enheten."
+#~ msgid "Device is now safe to remove"
+#~ msgstr "Enheten kan nu kopplas från"
+#~ msgid "The device %s is now safe to remove."
+#~ msgstr "Enheten %s kan nu kopplas från."
+#~ msgid "Unmounted %s (using /etc/fstab)\n"
+#~ msgstr "Avmonterade %s (enligt /etc/fstab)\n"
+#~ msgid "Unmounted %s\n"
+#~ msgstr "Avmonterade %s\n"
+#~ msgid "Ejected %s (using /etc/fstab).\n"
+#~ msgstr "Matade ut %s (enligt /etc/fstab).\n"
+#~ msgid "Ejected %s\n"
+#~ msgstr "Matade ut %s\n"
+#~ msgid ""
+#~ "The storage device %s contains encrypted data. Enter a password to unlock."
+#~ msgstr ""
+#~ "Lagringsenheten %s innehåller krypterat data. Ange ett lösenord för att "
+#~ "låsa upp."
+#~ msgid "Setup clear-text device for %s.\n"
+#~ msgstr "Konfigurera klartextenhet för %s.\n"
+#~ msgid "Teared down clear-text device for %s.\n"
+#~ msgstr "Nedbruten klartextenhet för %s.\n"
+#~ msgid "Clear text device is %s. Mounting.\n"
+#~ msgstr "Klartextenheten är %s. Monterar.\n"
+#~ msgid "X display not available - using text-based operation.\n"
+#~ msgstr "X-display finns inte tillgänglig - använder textbaserad åtgärd.\n"
+#~ msgid "Resolved device file %s -> %s\n"
+#~ msgstr "Slog upp enhetsfilen %s -> %s\n"
+#~ msgid "Resolved pseudonym \"%s\" -> %s\n"
+#~ msgstr "Slog upp pseudonymen \"%s\" -> %s\n"
+#~ msgid "Cannot resolve pseudonym \"%s\" to a volume\n"
+#~ msgstr "Kan inte slå upp pseudonymen \"%s\" till en volym\n"
+#~ msgid "Use --hal-udi, --device or --pseudonym to specify volume\n"
+#~ msgstr "Använd --hal-udi, --device eller --pseudonym för att ange volym\n"
+#~ msgid "Given device '%s' is not a volume or a drive."
+#~ msgstr "Angivna enheten \"%s\" är inte en volym eller en enhet."
+#~ msgid "Cannot unmount and eject simultaneously"
+#~ msgstr "Kan inte avmontera och mata ut samtidigt"
+#~ msgid "Crypto volume '%s' is already setup with clear volume '%s'"
+#~ msgstr ""
+#~ "Kryptovolymen \"%s\" är redan konfigurerad med en klartextvolym \"%s\""
+#~ msgid "Bad crypto password"
+#~ msgstr "Felaktigt kryptolösenord"
+#~ msgid "Bailing out..."
+#~ msgstr "Avslutar..."
+#~ msgid "<b>Connection:</b>"
+#~ msgstr "<b>Anslutning:</b>"
+#~ msgid "<b>External:</b>"
+#~ msgstr "<b>Extern:</b>"
+#~ msgid "<b>Firmware:</b>"
+#~ msgstr "<b>Fast programvara:</b>"
+#~ msgid "<b>Label:</b>"
+#~ msgstr "<b>Etikett:</b>"
+#~ msgid "<b>Media:</b>"
+#~ msgstr "<b>Media:</b>"
+#~ msgid "<b>Model:</b>"
+#~ msgstr "<b>Modell:</b>"
+#~ msgid "<b>Mount Options:</b>"
+#~ msgstr "<b>Monteringsalternativ:</b>"
+#~ msgid "<b>Mount Point:</b>"
+#~ msgstr "<b>Monteringspunkt:</b>"
+#~ msgid "<b>Removable:</b>"
+#~ msgstr "<b>Flyttbar:</b>"
+#~ msgid "<b>Serial:</b>"
+#~ msgstr "<b>Serienummer:</b>"
+#~ msgid "<b>Settings</b>"
+#~ msgstr "<b>Inställningar</b>"
+#~ msgid "<b>Size:</b>"
+#~ msgstr "<b>Storlek:</b>"
+#~ msgid "<b>UUID:</b>"
+#~ msgstr "<b>UUID:</b>"
+#~ msgid "<b>Vendor:</b>"
+#~ msgstr "<b>Tillverkare:</b>"
+#~ msgid ""
+#~ "<small><i>Changes in settings will not take effect until the\n"
+#~ "volume is remounted.</i></small>"
+#~ msgstr ""
+#~ "<small><i>Ändringar i inställningarna kommer att börja gälla\n"
+#~ "först nästa gång du monterar volymen.</i></small>"
+#~ msgid ""
+#~ "<small><i>Settings for a drive affects all volumes inserted in\n"
+#~ "the drive. This can be overriden for individual \n"
+#~ " volumes using the \"Volume\" tab.</i></small>"
+#~ msgstr ""
+#~ "<small><i>Inställningar för en enhet påverkar alla volymer som\n"
+#~ "är inmatade i enheten. Detta kan åsidosättas för individuella \n"
+#~ " volymer under fliken \"Volym\".</i></small>"
+#~ msgid "Removable Hard Disk"
+#~ msgstr "Flyttbar hårddisk"
+#~ msgid "Hard Disk"
+#~ msgstr "Hårddisk"
+#~ msgid "Blank DVD-R Disc"
+#~ msgstr "Tom dvd-r-skiva"
+#~ msgid "DVD-R Disc"
+#~ msgstr "Dvd-r-skiva"
+#~ msgid "Blank DVD+R Dual Layer Disc"
+#~ msgstr "Tom dvd+r-skiva (dubbla lager)"
+#~ msgid "DVD+R Dual Layer Disc"
+#~ msgstr "Dvd+r-skiva (dubbla lager)"
+#~ msgid "Blank BD-RE Disc"
+#~ msgstr "Tom bd-re-skiva"
+#~ msgid "BD-RE Disc"
+#~ msgstr "Bd-re-skiva"
+
diff --git a/trunk/po/ta.po b/trunk/po/ta.po
new file mode 100644
index 00000000..1cd04ae8
--- /dev/null
+++ b/trunk/po/ta.po
@@ -0,0 +1,1667 @@
+# translation of gvfs.HEAD.po to Tamil
+# translation of gvfs.HEAD.ta.po to
+# Translation of gvfs.HEAD_ta.po to தமிழ்
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+#
+# தங்கம் அருண் <thangam.arunx@gmail.com>, 2008..
+# I. Felix <ifelix@redhat.com>, 2008.
+# Dr.T.vasudevan <agnihot3@gmail.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-04 19:03+0000\n"
+"PO-Revision-Date: 2009-03-04 21:24+0530\n"
+"Last-Translator: Dr.T.vasudevan <agnihot3@gmail.com>\n"
+"Language-Team: Tamil <Ubuntu-l10n-tam@lists.ubuntu.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "செயல்பாடு துணைபுரியவில்லை, பல்வேறு ஏற்றங்களில் கோப்புகள் உள்ளன"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info இலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info இலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "இணைப்பு கோப்பு குறிப்பியைப் பெற முடியவில்லை"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "திறப்பதிலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "இணைப்பு கோப்பின் குறிப்பியைப் பெறவில்லை"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "அழைப்பிலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info இலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "இணைப்பட்ட ஏற்றத்தை காண முடியவில்லை"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "தவறான கோப்பு பெயர் %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "guery_filesystem_info இலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir இலிருந்து திருப்பி கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file இலிருந்து கொடுக்கப்பட்ட தவறான மதிப்பு"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "செயல்பாடு ரத்து செய்யப்பட்டது"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "தொடர்பு நெறிமுறையில் பிழை: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "இணைப்பின் முடிவு"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "இணைப்பில் தேடலுக்கு துணையில்லை"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "வினா தகவல் செயல்பாடு துணைபுரிவதில்லை"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+#| msgid "Seek not supported on stream"
+msgid "Query info not supported on stream"
+msgstr "ஓடையில் தேடல் தகவலுக்கு ஆதரவில்லை"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "ஏற்றி தகவலைப் பெறும் போது பிழை: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "டீமானுடன் இணைக்கப்படும் போது பிழை: %s"
+
+#: ../client/gvfsiconloadable.c:145
+#| msgid "Invalid return value from get_info"
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read இலிருந்து திரும்பிய செல்லுபடியாகாத மதிப்பு"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "சாக்கெட்டை உருவாக்கும் போது பிழை : %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "சாக்கெட்டை இணைக்கும் போது பிழை: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "தவறான கோப்புத் தகவல் வடிவம்"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "தவறான அளவு தகவல் பட்டியல் உள்ளடக்கம்"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error deleting file: %s"
+msgid "Error initializing Avahi: %s"
+msgstr "ஆவாஹி யை துவக்குதலில் பிழை: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating socket: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "ஆவாஹி தீர்வியை உருவாக்கும் போது பிழை : %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr " \"%s\" சேவை \"%s\" ஐ \"%s\" களத்தில் தீர்ப்பதில் பிழை."
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr " \"%s\" சேவை \"%s\" ஐ \"%s\" களத்தில் தீர்ப்பதில் பிழை.ஒன்றோ அதிகமாகவோ TXT பதிவுகள் காணவில்லை. தேவையான விசைகள்: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr " \"%s\" சேவை \"%s\" ஐ \"%s\" களத்தில் தீர்ப்பதில் காலாவதியானது"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "சிதைந் dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon வடிவுநிலை %d இன் குறியாக்கத்தை கையாள முடியவில்லை"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon க்கு சிதைந்த உள்ளீட்டு தரவு."
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Busஐ இணைக்கும் போது பிழை: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s கோப்பு முறைமை சேவை"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "பிழை: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "பயன்பாடு: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "பயன்பாடு: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ஏற்ற வகை குறிப்பிடப்படவில்லை"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%sக்கான ஏற்றிப்புள்ளி ஏற்கனவே இயக்கத்திலுள்ளது"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "டீமானை ஏற்றும் போது பிழை"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s இல் /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "புரவலன் பெயர் குறிப்பிடப்படவில்லை"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "தவறான ஏற்ற குறிப்பீடு"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:399
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:647
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "கோப்பு இல்லை"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:446
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:694
+msgid "The file is not a directory"
+msgstr "கோப்பு அடைவாகாது"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "எழுதுதல்"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "தற்காலிக கோப்பினை உருவாக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "எந்த கோப்பு அல்லது அடைவும் இல்லை"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "அடைவு வெற்றாக இல்லை"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "அடைவில் கோப்பினை நகலெடுக்க முடியாது"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD Creator"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "கோப்பு உள்ளது"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "செயல்பாடு பின்புலத்தால் துணைபுரியவில்லை"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "இலக்கு பாதையில் கோப்பு அல்லது அடைவு இல்லை"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "அடைவில் அடைவை நகலெடுக்க முடியாது"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "இலக்கு கோப்பு உள்ளது "
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "கோப்பினை நகர்த்த முடியாது"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "துணைபுரியவில்லை"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+#| msgid "Could not connect to host"
+msgid "Cannot connect to the system bus"
+msgstr "கணினி பஸ் உடன் இணைக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "லிப்ஹால் சூழலை உருவாக்க முடியாது"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "லிப்ஹால் ஐ துவக்க முடியாது"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "எந்த இயக்கியும் குறிப்பிடப்படவில்லை"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "இயக்கி %sஐ கண்டுபிடிக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "இயக்கி %s இசை கோப்புகளை வைத்திருக்கவில்லை "
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s இல் cdda ஏற்றி"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "இசை வட்டு"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "கோப்பு முறைமை வேலையாக உள்ளது: %d திறந்த கோப்பு"
+msgstr[1] "கோப்பு முறைமை வேலையாக உள்ளது: %d திறந்த கோப்புகள்"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "கோப்பு %s இயக்கி %sயில் இல்லை"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "இயக்கி %s இல் 'paranoia'இலிருந்து பிழை"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "%s இயக்கியல் இணைப்பை தேடும் போது பிழை"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "எந்த கோப்பும் இல்லை"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "கோப்பு இல்லை அல்லது அது இசை பாதையாக இருக்காது"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "இசை குறுவட்டு கோப்பு முறைமை சேவை"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "கணினி"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "கோப்பு முறைமை"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "அடைவை திறக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "ஏற்றக்கூடிய கோப்பினை திறக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "உள்ளார்ந்த பிழை: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "கோப்பினை ஏற்றி முடியவில்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "எந்த ஊடகமும் இயக்கியில் இல்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "ஏற்றிக்கூடிய கோப்பு இல்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "கோப்பினை ஏற்றம் நீக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "கோப்பினை வெளியேற்ற முடியவில்லை"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP பிழை: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "பதிலை பகுக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "வெற்று பதில்"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "சேவையகத்திலிருந்து எதிர்பாராத பதில்"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "தவறான பதில்"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV பங்கீடு"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "%sக்கு கடவுச்சொல்லை உள்ளிடவும்"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "உங்கள் பதிலாள் கடவுச்சொல்லை உள்ளிடவும்"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "WebDAV-செயல்படுத்தப்பட்ட பங்கீடு இல்லை"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+#| msgid "WebDAV share"
+msgid "WebDAV on %s"
+msgstr "%s இல் WebDAV பங்கீடு"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "கோரிக்கையை உருவாக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "இலக்கில் கோப்பு ஏற்கனவே உள்ளது "
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "கோப்பு வெளியில் மாற்றப்பட்டுள்ளது"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "பின்சேமிப்பு கோப்பினை உருவாக்க முடியவில்லை"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:493 ../daemon/gvfsbackendnetwork.c:394
+msgid "Local Network"
+msgstr "உள்ளமை பிணையம்"
+
+#: ../daemon/gvfsbackenddnssd.c:737 ../daemon/gvfsbackendnetwork.c:798
+msgid "Can't monitor file or directory."
+msgstr "கோப்பு அல்லது அடைவை கண்காணிக்க முடியவில்லை."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:755
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:756 ../daemon/gvfsbackendnetwork.c:733
+#: ../daemon/gvfsbackendnetwork.c:883 ../daemon/gvfsbackendnetwork.c:884
+msgid "Network"
+msgstr "பிணையம்"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "கணக்குகள் துணைபுரியவில்லை"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "புரவலன் மூடப்பட்ட இணைப்பு"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "தரவு இணைப்பை திறக்க முடியவில்லை. உங்கள் ஃபயர்வால் இதனை தடுக்கிறதா?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "தரவு இணைப்பு இல்லை"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "செயல்பாடு செயலிழக்கப்பட்டது"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "சேவையகத்தில் இடம் இல்லை"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "துணைபுரியாத செயல்பாடு"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "அனுமதி மறுக்கப்பட்டது"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "தெரியாத பக்கம் வகை"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "தவறான கோப்பு பெயர்"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "தவறான பதில்"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "பிளவுப்பட்ட பரிமாற்றம்"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "புரவலனுடன் இணைக்க முடியவில்லை"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+#| msgid "Enter password for ftp on %s"
+msgid "Enter password for ftp as %s on %s"
+msgstr "ftp கடவுச்சொல்லை %s ஆக %s அன்று உள்ளிடவும்"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "ftp கடவுச்சொல்லை %sஇல் உள்ளிடவும்"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "கடவுச்சொல் உரையாடல் ரத்தானது"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s இல் ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s இல் %s ஆக ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "கோப்பு அடைவு ஆகாது"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "இதுவரை பின்சேமிப்புகள் துணைபுரியவில்லை"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "மிக நீளமான கோப்பு பெயர்"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "தவறான இலக்கு கோப்பு பெயர்"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+#| msgid "%s: %s: error opening file: %s\n"
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: அடைவு அல்லது கோப்பு உள்ளது."
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+#| msgid "No such file or directory"
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: அப்படி எந்த கோப்பு அல்லது அடைவும் இல்லை"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+#| msgid "Invalid filename"
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d:செல்லுபடியாகாத கோப்பு பெயர்"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+#| msgid "Not supported"
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ஆதரவில்லை"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "டிஜிட்டல் நிழற்பட கருவி (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s நிழற்பட கருவி"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s இசை இயக்கி"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "நிழற்பட கருவி"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "இசை இயக்கி"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+#| msgid "No drive specified"
+msgid "No device specified"
+msgstr "எந்த சாதனமும் குறிப்பிடப்படவில்லை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "ஜிபோட்டோ2 சூழலை உருவாக்க முடியாது"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+#| msgid "Error creating socket: %s"
+msgid "Error creating camera"
+msgstr "காமிராவை உருவாக்கும் போது பிழை "
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "சாதனத்தின் தகவலை ஏற்றும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "சாதனத்தின் தகவலை காணும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "சாதனத்தின் தகவலை பெறும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "காமிரா இணைப்பு துறையை அமைக்கும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "காமிராவை துவக்கும் போது பிழை"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 %sஇல் ஏற்றப்பட்டது"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+#| msgid "No hostname specified"
+msgid "No camera specified"
+msgstr "காமிரா ஏதும் குறிப்பிடப்படவில்லை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+#| msgid "Error creating backup file: %s"
+msgid "Error creating file object"
+msgstr "கோப்பு பொருளை உருவாக்கும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+#| msgid "Error deleting file: %s"
+msgid "Error getting file"
+msgstr "கோப்பு பெறுதலில் பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+#| msgid "Error removing target file: %s"
+msgid "Error getting data from file"
+msgstr "கோப்பிலிருந்து தகவலை பெறும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "சிதைந்த சின்னம் அடையாளம் காணி '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+#| msgid "Error seeking in stream on drive %s"
+msgid "Error seeking in stream on camera %s"
+msgstr "%s காமிரா ஓடையில் தேடும் போது பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "ஒரு அடைவு அல்ல"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+#| msgid "File doesn't exist"
+msgid "Failed to get folder list"
+msgstr "அடைவு பட்டியலை பெறுதல் தோல்வியுற்றது"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+#| msgid "Target file exists"
+msgid "Failed to get file list"
+msgstr "கோப்பு பட்டியலை பெறுதல் தோல்வியுற்றது"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+#| msgid "Error creating socket: %s"
+msgid "Error creating directory"
+msgstr "அடைவை உருவாக்கும் போது பிழை "
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+#| msgid "Target file already exists"
+msgid "Name already exists"
+msgstr "இந்த பெயர் ஏற்கனவே உள்ளது "
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+#| msgid "filename too long"
+msgid "New name too long"
+msgstr "புதிய பெயர் மிக நீளமானது "
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+#| msgid "Error sending fd: %s"
+msgid "Error renaming dir"
+msgstr "அடைவை மறு பெயரிடுவதில் பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+#| msgid "Error moving file: %s"
+msgid "Error renaming file"
+msgstr "கோப்பை மறு பெயரிடுவதில் பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+#| msgid "Directory not empty"
+msgid "Directory '%s' is not empty"
+msgstr "அடைவு '%s' வெற்றாக இல்லை"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+#| msgid "Error deleting file: %s"
+msgid "Error deleting directory"
+msgstr "அடைவை அழித்தலில் பிழை:"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+#| msgid "Error deleting file: %s"
+msgid "Error deleting file"
+msgstr "கோப்பு அழித்தலில் பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+#| msgid "Can't open directory"
+msgid "Can't write to directory"
+msgstr "அடைவுக்கு எழுத முடியவில்லை"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "பின்னால் சேர்ப்பதற்கு புதிய கோப்பு ஒன்றை ஒதுக்க முடியாது"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "பின்னால் சேர்ப்பதற்கு கோப்பை படிக்க முடியாது"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "பின்னால் சேர்ப்பதற்கு கோப்பு தரவை பெற முடியாது"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+#| msgid "Error deleting file: %s"
+msgid "Error writing file"
+msgstr "கோப்பு எழுதுதலில் பிழை"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+#| msgid "Not a directory"
+msgid "Not supported (not same directory)"
+msgstr "ஆதரவில்லை (அதே அடைவு அல்ல)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "ஆதரவில்லை ( மூலம் அதே அடைவு, இலக்கு அதே அடைவு)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "ஆதரவில்லை ( மூலம் அடைவு, இலக்கு இருப்பு கோப்பு)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "ஆதரவில்லை ( மூலம் கோப்பு, இலக்கு அடைவு)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP சார்ந்தோன் பிழை: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (தவறான குறிமுறை)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "அடைவு அறிவிப்பு துணைபுரியவில்லை"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "விண்டோஸ் பிணையம்"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:932
+msgid "Network Location Monitor"
+msgstr "பிணைய இட கண்காணி"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s இல் %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "யூஎஸ்பி ஆதரவு இல்லை. தயை செய்து உங்கள் மென்பொருள் விற்பனையாளரை தொடர்பு கொள்க. "
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "சாதனத்துக்கு தொடர்பு அற்றுப்போயிற்று."
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "சாதனத்துக்கு மென்பொருள் இற்றைப்படுத்தல் அவசியம்."
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh நிரல் எதிர்பாராமல் வெளியேறியது "
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "புரவலன் பெயர் தெரியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "நிறுவ வழித்தடம் எதுவும் இல்லை"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "சேவையகத்தால் இணைப்பு தவிர்க்கப்பட்டது"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "புரவலன் குறியீட்டை சரி பார்க்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh நிரலை உருவாக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh நிரலை உருவாக்க முடியவில்லை: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "புகுபதிவு நேரம் முடிவடைந்தது"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "குறியீட்டிற்கு கடவுச்சொல்லை உள்ளிடவும்"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "கடவுச்சொல்லை உள்ளிடவும்"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "கடவுச்சொல்லை அனுப்ப முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "எவ்வாறேனும் புகுபதிவு செய்யவும்"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "புகுபதிவை ரத்து செய்யவும்"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"தொலைவில் உள்ள கணினியின் (%s) குறிப்பு தெறியவில்லை .\n"
+"முதல் முறை அந்த கணினியில் உள் நுழையும்போது அந்த மாதிரி விழையும்.\n"
+"\n"
+"தொலைவில் உள்ள கணினி (%s) அனுப்பிய குறிப்பு. உங்களுக்கு கண்டிப்பாக வேண்டுமானால் "
+"தொடருங்கள், கணினி மேலாளரை அனுகுங்கள்."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "புகுபதிவு உரையாடல் ரத்தானது"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "புரவலன் அடையாள உறுதிப்படுத்தலை அனுப்ப முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "நெறிமுறை பிழை"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+#| msgid "ftp as %s on %s"
+msgid "sftp for %s on %s"
+msgstr "%s க்கு sftp %s இல்"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "%sஇல் sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "துணைபுரியும் sshஇன் கட்டளையை கண்டுபிடிக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "தோல்வி"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "தவறான பதில் கிடைத்துள்ளது"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead இல் செல்லுபடியாகாத icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "பின்சேமிப்பு கோப்பினை உருவாக்க போது பிழை: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "தற்காலிக கோப்பினை உருவாக்க முடியவில்லை"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "அடைவை ஒன்றின் மேல் ஒன்றாக நகர்த்த முடியவில்லை"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "பங்கீடு %s இல் %sக்கு கடவுச்சொல் தேவைப்படுகிறது"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "உள்ளார்ந்த பிழை (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "விண்டோஸ் பங்கீட்டை ஏற்ற முடியவில்லை"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "துணைபுரியாத தேடும் வகை"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "பின்சேமிப்பு கோப்பினை உருவாக்க முடியவில்லை: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "கோப்பு அழித்தலில் பிழை: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "கோப்பு நகர்த்துவதில் பிழை: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "இலக்கு கோப்பினை நீக்க முடியவில்லை: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "அடைவை நகர்த்த முடியவில்லை"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "விண்டோஸ் பங்கீடு கோப்பு முறைமை சேவை"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+#| msgid "Password required for share %s on %s"
+msgid "Password required for %s"
+msgstr " %sக்கு கடவுச்சொல் தேவைப்படுகிறது"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%sஇல் விண்டோஸ் பங்கீடுகள்"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "சேவையகத்தில் இருந்து பங்கீட்டு பட்டியலை மீட்பது தோல்வியுற்றது"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "கோப்பு ஏற்றித்தக்கதல்ல"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "ஒழுங்கான கோப்பு அல்ல"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "விண்டோஸ் பிணைய கோப்பு முறைமை சேவை"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "குப்பை அடைவை நீக்க முடியாது"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "குப்பையில் உள்ள உருப்படிகளை மாற்ற முடியாது "
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "மீள்சேமிப்பு"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "தவறான பின்புல வகை"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fdயை அனுப்புவதில் பிழை: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Symlinks பின்புலத்தால் துணைபுரிவதில்லை"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "தவறான dbus தகவல்"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "பழைய டீமானை மாற்றவும்."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "fuse ஐ துவக்க வேண்டாம்."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS டீமான்"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFSக்கான முக்கியமான டீமான்"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "மேலும் தகவலுக்கு \"%s --help\"ஐ முயற்சிக்கவும்."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "உருவாக்கப்பட்ட சேயிலிருந்து தவறான அளவுருக்கள்"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount செயலிழக்கப்பட்டது: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "குறிப்பிடப்பட்ட இடத்தை ஏற்ற முடியவில்லை"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "குறிப்பிடப்பட்ட இடத்தை ஏற்ற முடியவில்லை"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "இடம் ஏற்கனவே ஏற்றப்பட்டள்ளது"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "இடம் ஏற்றப்படுமாறு இல்லை"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "வெற்று CD-ROM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "வெற்று CD-R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "வெற்று CD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "வெற்று DVD-ROM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "வெற்று DVD-RAM வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "வெற்று DVD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "வெற்று DVD+R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "வெற்று DVD+RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "வெற்று DVD+R DL வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "வெற்று Blu-Ray வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "வெற்று Blu-Ray R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "வெற்று Blu-Ray RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "வெற்று HD DVD வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "வெற்று HD DVD-R வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "வெற்று HD DVD-RW வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "வெற்று MO வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "வட்டு"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "வெற்று வட்டு"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s இயக்கி"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "நெகிழ்வட்டு இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "மென்பொருள் RAID இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "நாடா இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "ஜிப் இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "அதிகமாக சேமிக்கும் இயக்கி"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "ஊடகத்தை வெளியேற்ற முடியவில்லை, ஊடகத்தில் ஒன்று அல்லது பல தொகுதிகள் பணியில் இருக்கலாம்."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "இசை/தரவு கலந்த வட்டு"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s ஊடகம்"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s மறைகுறியாக்கப்பட்ட தரவு"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s : கோப்பினை திறப்பதில் பிழை: %s \n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdoutக்கு எழுதும் போது பிழை"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: வாசிப்பதில் பிழை: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: மூடுவதில் பிழை: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "இடம்... - இடங்களை நிலையான வெளியீடு உடன் சேர்."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"கோப்புகளை இடங்களில் சேர் மற்றும் நிலையான வெளியிக்கு அச்சிடு. இது வலக்கமான cat "
+"செயலாற்றியை போல் வேலைச்செய்கிறது, ஆனால் சொந்த கோப்புகளுக்கு பதிலாக gvfs இடத்தைப் "
+"பயன்படுத்தும்எடுத்துக்காட்டாக இதுப்போன்ற smb://server/resource/file.txtபகுதிகளுக்குச் "
+"சேர்"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"குறிப்பு: சற்று பைப் வழியாக cat பன்னுங்க, உங்களுக்கு உருமாற்றும் வழிகள் -n, -T or "
+"தேவைப்பட்டால் அல்லதுமற்ற"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: விடுபட்ட இடங்கள்"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s : இடத்தை திறப்பதில் பிழை: %s \n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s : பயன்பாட்டை திறப்பதில் பிழை: %s \n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "கோப்புகள்... - திறந்த கோப்புகள் பயன்பாட்டுடன் பதிவானவை."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"திறந்த கோப்பு(கள்) ஏற்கனவேயுள்ள பயன்பாட்டுடன் பதிவானவைகள் மற்றும் கையாழக்கூடிய கோப்பு "
+"வகையை சரர்ந்தவை"
+
diff --git a/trunk/po/te.po b/trunk/po/te.po
new file mode 100644
index 00000000..60675af8
--- /dev/null
+++ b/trunk/po/te.po
@@ -0,0 +1,1626 @@
+# translation of gvfs.HEAD.po to Telugu
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Krishna Babu K <kkrothap@redhat.com>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-03 13:43+0000\n"
+"PO-Revision-Date: 2009-02-04 11:25+0530\n"
+"Last-Translator: Krishna Babu K <kkrothap@redhat.com>\n"
+"Language-Team: Telugu <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "కార్యము మద్దతీయబడదు, దస్త్రములు భిన్నమైన మౌంట్‌లనందు వున్నవి"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info నుండి చెల్లని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info నుండి చెల్లని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "స్ట్రీమ్ దస్త్రం వివరణిని పొందలేకపోయింది"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "తెరువుట నుండి చెల్లని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "స్ట్రీమ్ దస్త్రం వివరిణిని పొందలేదు"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "కాల్ నుండి చెల్లని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info నుండి చెల్లని తిరుగు విలువ"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "ఎన్‌క్లోసింగ్ మౌంట్ ను కనుగొనలేక పోయింది"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "సరికాని దస్త్రనామము %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info నుండి సరికాని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir నుండి సరికాని తిరుగు విలువ"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file నుండి సరికాని తిరుగు విలువ"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "కార్యము రద్దుచేయబడింది"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "స్ట్రీమ్ నియమం నందు దోషం: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "స్ట్రీమ్ యొక్క ముగింపు"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "స్ట్రీమ్ పై సీక్ మద్దతీయబడదు"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "సవాలు సమాచారం కార్యము మద్దతీయబడదు"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "క్వరీ సమాచారం స్ట్రీమ్‌నందు మద్దతీయబడదు"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "మౌంట్ సమాచారాన్ని పొందునప్పుడు దోషం: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "డెమోన్ కు అనుసంధానించబడుతున్నప్పుడు దోషం: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr ""
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "సాకెట్ సృష్టించుటలో దోషం: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "సాకెట్ కు అనుసంధానించుటలో దోషం: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "సరికాని దస్త్రం సమాచారం రూపం"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "చెల్లని యాట్రిబ్యూట్ సమాచారం జాబితా సారం"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr ""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr ""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr ""
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr ""
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus కు అనుసంధానించుటలో దోషం: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s ఫైల్‌సిస్టమ్ సేవ"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "దోషం: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "ఉపయోగం: %s --స్పానర్ dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "ఉపయోగం: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ఏ మౌంట్ రకం తెలుపలేదు"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s కొరకు మౌంట్‌సూచి ఇప్పటికే నడుస్తోంది"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "మౌంట్ డెమోన్ ను ప్రారంభించుటలో దోషం"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s పై /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "ఏ అతిధేయనామము తెలుపబడలేదు"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "చెల్లని మౌంట్ స్పెక్"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:399
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:647
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "దస్త్రం లేదు"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:446
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:694
+msgid "The file is not a directory"
+msgstr "ఆ దస్త్రము సంచయంకాదు"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "వ్రాయుము"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "తాత్కాలిక సంచయాన్ని సృష్టించలేదు"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "అటువంటి దస్త్రముగాని లేదా సంచయంగాని లేదు"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "సంచయం ఖాళీగా లేదు"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "సంచయంనుండి దస్త్రమును నకలుతీయలేము"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD సృష్టీకరణి"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "దస్త్రం ఉంది"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "బ్యాక్ఎండ్ చేత కార్యము మద్దతునీయబడదు"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "లక్ష్య మార్గమునందు అటువంటి దస్త్రముగాని లేదా సంచయంగాని లేదు"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "సంచయంనందు సంచయంను నకలుతీయలేము"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "లక్ష్యపు దస్త్రము ఉంది"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "సంచయంను మరలమరలా నకలు తీయలేము"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "మద్దతీయబడదు"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "సిస్టమ్ బస్‌కు అనుసంధానం కాలేదు"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "libhal సందర్భంను సృష్టించలేదు"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "libhalను సిద్దము చేయలేదు"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "ఏ డ్రైవ్ తెలుపబడలేదు"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "డ్రైవ్ %s ను కనుగొనలేకపోయింది"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "డ్రైవ్ %s ఆడియో దస్త్రములను కలిగిలేదు"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda %sనందు మౌంట్ అయినది"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "ఆడియో డిస్కు"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "దస్త్ర వ్యవస్థ రద్దీగా ఉంది: %d తెరిచిన దస్త్రం"
+msgstr[1] "దస్త్ర వ్యవస్థ రద్దీగా ఉంది: %d తెరిచిన దస్త్రం"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "%2$s డ్రై నందు %1$s లాంటి దస్త్రం లేదు"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "డ్రైవ్ %s పైన 'paranoia' నుండి దోషం"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "డ్రైవ్ %s పైన స్ట్రీమ్ నందు దోషం వెతుకుతోంది"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "అటువంటి దస్త్రం లేదు"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ఆ దస్త్రం లేదు లేదా అది ఆడియో ట్రాక్ కాదు"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "ఆడియో CD దస్త్రవ్యవస్థ సేవ"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "కంప్యూటర్"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "దస్త్రవ్యవస్థ"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "సంచయంను తెరువలేదు"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "మౌంటబుల్ దస్త్రాన్ని తెరువలేదు"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "అంతర్గత దోషం: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "దస్త్రాన్ని మౌంట్ చేయలేము"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "డ్రైవ్‌నందు యెటువంటి మాధ్యమం లేదు"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "మౌంటబుల్ దస్త్రం కాదు"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "దస్త్రాన్ని అన్‌మౌంట్ చేయలేము"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "దస్త్రాన్ని బయటకు పంపలేము"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP దోషం: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "ప్రతిస్పందనను పార్శ్ చేయలేము"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "ఖాళీ ప్రతిస్పందన"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "సేవికనుండి అనుకోని ప్రత్యుత్తరము"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "ప్రతిస్పందన చెల్లనిది"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV భాగస్వామ్యం"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s కొరకు సంకేతపదాన్ని ప్రవేశపెట్టుము"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "ప్రాక్సీ సంకేతపదంను ప్రవేశపెట్టండి"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "అది WebDAV చేతనమైన భాగస్వామ్యంకాదు"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s నందు WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "అభ్యర్ధనను సృష్టించలేక పోయింది"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "లక్ష్యపు దస్త్రం ఇప్పటికే ఉంది"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "ఆ దస్త్రం బహిర్గతంగా సవరించబడింది"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "బ్యాక్‌అప్ దస్త్రం సృష్టీకరణ విఫలమైంది"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:493 ../daemon/gvfsbackendnetwork.c:394
+msgid "Local Network"
+msgstr "స్థానిక నెట్వర్క్‍"
+
+#: ../daemon/gvfsbackenddnssd.c:737 ../daemon/gvfsbackendnetwork.c:798
+msgid "Can't monitor file or directory."
+msgstr "దస్త్రమును లేదా డైరెక్టరీని పర్యవేక్షించలేదు."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:755
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:756 ../daemon/gvfsbackendnetwork.c:733
+#: ../daemon/gvfsbackendnetwork.c:883 ../daemon/gvfsbackendnetwork.c:884
+msgid "Network"
+msgstr "నెట్ వర్క్"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "ఖాతాలు మద్దతీయనివి"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "హోస్ట్‍ అనుసంధానంను మూసివేసినది"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "డాటా అనుసంధానంను తెరువలేదు. బహుశా మీ ఫైర్‌వాల్ దీనిని నిరోధిస్తోందా?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "డాటా అనుసంధానం ముయబడింది"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "ఆపరేషన్ విఫలమైంది"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "సేవికనందు ఖాళీ మిగిలిలేదు"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "ఆపరేషన్ మద్దతీయుటలేదు"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "అనుమతి తిరస్కరించబడినది"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "పుట రకము తెలియనిది"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "చెల్లని దస్త్రమునామము"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "చెల్లని ప్రత్యుత్తరము"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "విరిగిన బదిలీకరణ"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "హోస్ట్‍‌కు అనుసంధానం కాలేకపోయింది"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr ""
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%sపైన ftp కొరకు సంకేతపదమును ప్రవేశపెట్టండి"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "సంకేతపదం డైలాగ్ రద్దుచేయబడింది"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s పైన ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%2$s పైన %1$sలా ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "దస్త్రము సంచయం"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "బ్యాక్అప్స్‍ యింకా మద్దతునీయుటలేదు"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "దస్త్రమునామము మరీ పొడవైనది"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "గమ్య దస్త్రనామము చెల్లనిది"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: డైరెక్టరీ లేదా దస్త్రము వుంది"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: అటువంటి దస్త్రము లేదా డైరక్టరీ లేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: చెల్లని దస్త్రనామము"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: మద్దతీయుటలేదు"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "డిజిటల్ కామెరా(%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s కేమెరా"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s ఆడియో ప్లేయర్"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "కేమెరా"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "ఆడియో ప్లేయర్"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "ఎటువంచి పరికరము తెలుపబడలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 సందర్భంను సృష్టించలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "కామెరా సృష్టించుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "పరికరము సమాచారం లోడ్‌చేయుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "పరికరము సమాచారం చూడుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "పరికరము సమాచారం పొందుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "కామెరా సంప్రదింపుల పోర్ట్‍‌ను అమర్చుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "కామెరాను సిద్దముచేయుటలో దోషము"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s పై gphoto2 మౌంట్"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "ఎటువంటి కామెరా తెలుపబడలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "దస్త్రము ఆబ్జక్‌ను సృష్టించుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "దస్త్రమును పొందుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "దస్త్రమునుండి డాటాను పొందుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr ""
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "కామెరా %s నందు స్ట్రీమ్ సీకింగ్ దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "సంచయం కాదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "సంచయం జాబితాను పొందుటలో విఫలమైంది"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "దస్త్రము జాబితాను పొందుటలో విఫలమైంది"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "డైరెక్టరీ సృష్టించుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "నామము యిప్పటికే వుంది"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "కొత్త నామము మరీ పొడవైనది"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "డైరెక్టరీ పునఃనామకరణ చేయుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "దస్త్రము పునఃనామకరణలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "డైరెక్టరీ '%s'లో ఖాళీలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "డైరక్టీ తొలగించుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "దస్త్రము తొలగించుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "డైరక్టరీకి వ్రాయలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "దీనికి కలుపుటకు కొత్త దస్త్రమును కేటాయించలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "దీనికి కలుపుటకు దస్త్రమును చదువలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "దీనికి కలుపుటకు దస్త్రముయొక్క డాటాను పొందలేదు"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "దస్త్రముకు వ్రాయుటలో దోషము"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "మద్దతీయుటలేదు (అదే డైరక్టరీకాదు)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "మద్దతీయుటలేదు (మూలం డైరెక్టరీనే, గమ్యం డైరక్టరీనే)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "మద్దతీయుట లేదు (మూలం డైరెక్టరీ, గమ్యం కలిగివున్న దస్త్రము)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "మద్దతీయుటలేదు (మూలం దస్త్రము, గమ్యం డైరెక్టరీ)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP కక్షిదారి దోషం: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (సరికాని ఎన్కోడింగ్)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "సంచయం ప్రకటన మద్దతిచ్చునదికాదు"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "విండోస్ నెట్వర్కు"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:932
+msgid "Network Location Monitor"
+msgstr "నెట్వర్క్‍ స్థానము పర్యవేక్షణి"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s పైన %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr ""
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "పరికరమునకు అనుసంధానం కోల్పోయింది"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "పరికరంకు సాఫ్ట్‍‌వేర్ నవీకరణ అవసరము"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh ప్రోగ్రామ్ అనుకోకుండా బయటకువచ్చింది"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "అతిధేయనామము తెలియనిది"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "అతిధేయ కు ఏ రూట్ లేదు"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "సేవిక చేత అనుసంధానం తిరస్కరించబడింది"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "అతిధేయ కీ నిర్ధారణ విఫలమైంది"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh ప్రోగ్రమ్ ను విస్తరింప లేదు"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh ప్రోగ్రామ్ ను విస్తరింపలేదు: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "లాగిన్ అవుతున్నప్పుడు కాలముమించినది"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "కీ కొరకు సంకేతపదాన్ని ప్రవేశపెట్టండి"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "రహస్య పదమును ప్రవేశపెట్టండి"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "సంకేతపదాన్ని పంపలేదు"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "ఏవిధంగానైనా లాగిన్ అవ్వుము"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "లాగిన్ రద్దుచేయుము"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"దూరస్థ కంప్యూటర్ (%s)యొక్క గుర్తింపు తెలియనిది.\n"
+"మీరు కంప్యూటర్‌కు మొదటిసారి లాగిన్ అయినప్పుడు ఇది జరుగుతుంది.\n"
+"\n"
+"దూరస్థ కంప్యూటర్ ద్వారా పంపబడిన గుర్తింపు %s. మీరు యిలా కొనసాగించుట ఖచ్చితంగా సురక్షితమైన "
+"అనుకుంటే, సిస్టమ్ నిర్వాహకుడను సంప్రదించండి."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "లాగిన్ డైలాగ్ రద్దుచేయబడింది."
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "హోస్ట్‍ గుర్తింపు నిర్ధారణను పంపలేదు"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "నియమం దోషం"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr ""
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "%s పై sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "మద్దతివ్వబడే ssh ఆదేశాన్ని కనుగొనలేకపోయింది"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "వైఫల్యం"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "చెల్లని ప్రత్యుత్తరం స్వీకరించబడింది"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr ""
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "బ్యాక్‌అప్ దస్త్రం సృష్టించటలో దోషం: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "తాత్కాలిక దస్త్రాన్ని సృష్టించలేక పోయింది"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "సంచయంను సంచయం మీదకు కదుపలేము"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%2$s పైన %1$s పంచుకోవడానికి సంకేతపదం అవసరం"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "అంతర్గత దోషం (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "విండోల భాగస్వామ్యాన్ని మౌంట్ చేయుటకు విఫలమైంది"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "మద్దతీయబడని సీక్ రకము"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "బ్యాక్అప్ దస్త్రము సృష్టీకరణ విఫలమైంది: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "దస్త్రము తొలగించుటలో దోషం: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "దస్త్రము కదుపుటలో దోషం: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "లక్ష్యపు దస్త్రంను తీసివేయుటలో దోషం: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "సంచయంను మరలమరలా కదుపలేము"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "విండోలు దస్త్రవ్యవస్థ సేవను పంచుకొంటాయి"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr ""
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s పైన విండోస్ భాగస్వామ్యం"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr ""
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "ఆ దస్త్రం మౌంటవునది కాదు"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "సాదారణ దస్త్రం కాదు"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "విండోస్ నెట్వర్క్‍ దస్త్రవ్యవస్థ సేవ"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#, c-format
+msgid "Can't delete trash"
+msgstr "చెత్తను తొలగించ లేదు"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr ""
+
+#: ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "Can't pull trash"
+msgstr ""
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "చెత్తకుండి"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "చెల్లని బ్యాక్ఎండ్ రకం"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd పంపుటలో దోషం: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "బ్యాక్ఎండ్ ద్వారా సిమ్‌లింక్స్ మద్దతునీయబడవు"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "సరికాని dbus సందేశం"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "ాత డెమోన్ ను పునఃస్థాపించుమ.ు"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "ఫ్యూజ్ ను ప్రారంభించ వద్దు."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS డెమోన్"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS కొరకు ముఖ్య డెమోన్"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "ఎక్కువ సమాచారం కొరకు \"%s --సహాయం\" ను ప్రయత్నించండి."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "ఉద్బవించిన శిశువునుండి చెల్లని ఆర్గుమెంట్లు"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "స్వయంచాలకమౌంట్ విఫలమైంది: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "తెలుపబడిన స్థానము మౌంట్ కాలేదు"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "తెలుపబడిన స్థానము మద్దతివ్వబడలేదు"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "స్థానము ఇప్పటికే మౌంటుఅయిఉంది"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "స్థానము మౌంటగునది కాదు"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "ఖాళీ CD-ROM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "ఖాళీ CD-R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "ఖాళీ CD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "ఖాళీ DVD-ROM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "ఖాళీ DVD-RAM డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "ఖాళీ DVD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "ఖాళీ DVD+R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "ఖాళీ DVD+RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "ఖాళీ DVD+R DL డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "ఖాళీ Blu-Ray డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "ఖాళీ Blu-Ray R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "ఖాళీ Blu-Ray RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "ఖాళీ HD DVD డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "ఖాళీ HD DVD-R డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "ఖాళీ HD DVD-RW డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "ఖాళీ MO డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "డిస్కు"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "ఖాళీ డిస్కు"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s డ్రైవ్"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ఫ్లాపీ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "సాఫ్టువేర్ RAID డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "ఫైర్‌వైర్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "టేప్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "కాంపాక్ట్‌ఫ్లాష్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "మెమొరీస్టిక్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "స్మార్ట్‌మాద్యమం డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "జిప్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "జాజ్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "థంబ్ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "అధిక నిల్వ డ్రైవ్"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "మాద్యమాన్ని బయటకు పంపుట విఫలమైంది, మాద్యమం పైని ఒకటి లేదా ఎక్కువ వాల్యూమ్స్ రద్దీగా ఉన్నాయి."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "మిశ్రమ ఆడియో/డాటా డిస్కు"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s మాద్యమం"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s ఎన్క్రిప్టెడ్ డాటా"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: దొషం దస్త్రాన్ని తెరువుటలో: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, దోషం stdout కు వ్రాస్తోంది"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: దోషం చదువుతోంది: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:దోషం మూసివేస్తోంది: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "స్థానము... - ప్రామాణిక అవుట్‌పుట్ కు స్థానములను కలుపుట."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"స్థానములవద్ద దస్త్రాలను కులుపుము మరియు ప్రామాణిక అవుట్‌పుట్ కు ముద్రించుము. ఇది సాంప్రదాయ cat "
+"సౌలబ్యంలాగా నే పనిచేస్తుంది, అయితే gvfs స్థానమును స్థానిక దస్త్రముల బదులుగా ఉపయోగిస్తుంది: ఉదాహరణకు "
+"మీరు smb://server/resource/file.txt వంటి దాన్ని స్థానముగా కలుపుటకొరకు ఉపయోగించవచ్చు."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "గమనిక: మీకు రూపీకరణ ఐచ్చికం -n, -T లేదా ఇతరం అవసరం అయితే cat గుండా పైప్ చేయుము."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: తప్పిపోయిన స్థానములు"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: దోషం స్థానము తెరువుటలో: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: దోషం అనువర్తనం దించుటలో: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "దస్త్రములు... - నమోదైన అనువర్తనం తో దస్త్రములను తెరువుము."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "ఈ రకమైన దస్త్రము(ల) ను సంభాలించుటకు నమోదైన అప్రమేయ అనువర్తనంతో దస్త్రము ను తెరువుము."
+
diff --git a/trunk/po/th.po b/trunk/po/th.po
new file mode 100644
index 00000000..d2d94f63
--- /dev/null
+++ b/trunk/po/th.po
@@ -0,0 +1,1674 @@
+# Thai translation for gvfs.
+# Copyright (C) 2008-2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gvfs package.
+#
+# Theppitak Karoonboonyanan <thep@linux.thai.net>, 2008-2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-12 20:44+0700\n"
+"PO-Revision-Date: 2009-02-12 21:02+0700\n"
+"Last-Translator: Theppitak Karoonboonyanan <thep@linux.thai.net>\n"
+"Language-Team: Thai <thai-l10n@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "ไม่รองรับการกระทำนี้ เนื่องจากแฟ้มอยู่ใต้จุดเมานท์คนละจุดกัน"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก get_info"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก query_info"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "ไม่สามารถหยิบ file descriptor ของสตรีมมาใช้ได้"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก open"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "ไม่สามารถหยิบ file descriptor ของสตรีมมาใช้ได้"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก call"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก get_filesystem_info"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "ไม่สามารถหาจุดเมานท์ที่บรรจุ"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "ชื่อแฟ้ม %s ใช้ไม่ได้"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก query_filesystem_info"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก monitor_file"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "ปฏิบัติการถูกยกเลิก"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "เกิดข้อผิดพลาดในโพรโทคอลของสตรีม: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "จบสตรีม"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "ไม่รองรับการเลื่อนตำแหน่งในสตรีม"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "ไม่รองรับการสอบถามข้อมูล"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "ไม่รองรับการสอบถามข้อมูลในสตรีม"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "เกิดข้อผิดพลาดขณะอ่านข้อมูลการเมานท์: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "เกิดข้อผิดพลาดขณะเชื่อมต่อไปยังดีมอน: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "มีการคืนค่าที่ใช้การไม่ได้จาก open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "เกิดข้อผิดพลาดขณะสร้างซ็อกเก็ต: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "เกิดข้อผิดพลาดขณะเชื่อมต่อไปยังซ็อกเก็ต: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "รูปแบบของข้อมูลเกี่ยวกับแฟ้มผิดพลาด"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "เนื้อหารายการข้อมูลคุณลักษณะผิดพลาด"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "เกิดข้อผิดพลาดขณะตั้งค่าเริ่มต้น Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "เกิดข้อผิดพลาดขณะสร้างตัวหาที่อยู่ของ Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "เกิดข้อผิดพลาดขณะเปิดหาบริการ \"%s\" ชื่อ \"%s\" ที่โดเมน \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"เกิดข้อผิดพลาดขณะเปิดหาบริการ \"%s\" ชื่อ \"%s\" ที่โดเมน \"%s\" ระเบียน TXT "
+"อย่างน้อยหนึ่งรายการหายไป คีย์ที่ต้องการคือ \"%s\""
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "หมดเวลาคอยขณะเปิดหาบริการ \"%s\" ชื่อ \"%s\" ที่โดเมน \"%s\""
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "encoded_triple '%s' ของ dns-sd ผิดรูปแบบ"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "ไม่สามารถจัดการกับรหัสของ GVfsIcon รุ่น %d ได้"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "ข้อมูลเข้าสำหรับ GVfsIcon ผิดรูปแบบ"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "เกิดข้อผิดพลาดขณะเชื่อมต่อไปยัง D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "บริการระบบแฟ้ม %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "ผิดพลาด: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "วิธีใช้: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "วิธีใช้: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "ไม่ได้ระบุชนิดของการเมานท์"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "จุดเมานท์สำหรับ %s ได้ทำงานอยู่แล้ว"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "เกิดข้อผิดพลาดขณะตั้งต้นดีมอนสำหรับเมานท์"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ ที่ %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "ไม่ได้ระบุชื่อโฮสต์"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "ข้อกำหนดการเมานท์ผิดพลาด"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "ไม่มีแฟ้มอยู่"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "แฟ้มดังกล่าวไม่ใช่ไดเรกทอรี"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "เขียนแผ่น"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "ไม่สามารถสร้างไดเรกทอรีชั่วคราว"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "ไม่มีแฟ้มหรือไดเรกทอรีดังกล่าว"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "ไดเรกทอรีไม่ว่าง"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "ไม่สามารถคัดลอกแฟ้มทับไดเรกทอรี"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "แบ็กเอนด์เขียนซีดี/ดีวีดี"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "แฟ้มมีอยู่แล้ว"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "แบ็กเอนด์ไม่รองรับปฏิบัติการ"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "ไม่มีแฟ้มหรือไดเรกทอรีดังกล่าวในพาธปลายทาง"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "ไม่สามารถคัดลอกไดเรกทอรีทับไดเรกทอรี"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "มีแฟ้มปลายทางอยู่แล้ว"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "ไม่สามารถคัดลอกไดเรกทอรีทั้งยวง"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "ไม่รองรับ"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "ไม่สามารถเชื่อมต่อไปยังบัสระบบ"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "ไม่สามารถสร้างบริบทสำหรับ libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "ไม่สามารถตั้งต้น libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "ไม่ได้ระบุไดรว์"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "หาไดรว์ %s ไม่พบ"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "ไดรว์ %s ไม่ได้บรรจุแฟ้มเสียง"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "การเมานท์ cdda ที่ %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "แผ่นเพลง"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "ระบบแฟ้มถูกใช้งานอยู่: เปิดแฟ้มอยู่ %d แฟ้ม"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "ไม่มีแฟ้ม %s ที่ว่าในไดรว์ %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "เกิดข้อผิดพลาดจาก 'paranoia' ที่ไดรว์ %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "เกิดข้อผิดพลาดขณะเลื่อนตำแหน่งในสตรีมที่ไดรว์ %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "ไม่มีแฟ้มดังกล่าว"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "ไม่มีแฟ้มดังกล่าวอยู่ หรือไม่ใช่ร่องเสียง"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "บริการระบบแฟ้มซีดีเพลง"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "คอมพิวเตอร์"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "ระบบแฟ้ม"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "ไม่สามารถเปิดไดเรกทอรี"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "ไม่สามารถเปิดแฟ้มสำหรับเมานท์"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "เกิดข้อผิดพลาดภายใน: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "ไม่สามารถเมาทน์แฟ้ม"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "ไม่มีสื่อในไดรว์"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "ไม่ใช่แฟ้มสำหรับเมานท์"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "ไม่สามารถเลิกเมาทน์แฟ้ม"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "ไม่สามารถดันแฟ้มออก"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "ข้อผิดพลาด HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "ไม่สามารถแจงคำตอบ"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "คำตอบว่างเปล่า"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "ได้รับคำตอบที่ไม่คาดหมายจากเซิร์ฟเวอร์"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "คำตอบใช้ไม่ได้"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "การเปิดให้ใช้ร่วมผ่าน WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "กรุณาป้อนรหัสผ่านสำหรับ %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "กรุณาป้อนรหัสผ่านสำหรับพร็อกซี"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "ไม่ใช่แหล่งใช้ร่วมที่ใช้ WebDAV ได้"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV ที่ %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "ไม่สามารถสร้างคำร้องขอ"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "มีแฟ้มปลายทางอยู่ก่อนแล้ว"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "แฟ้มถูกเปลี่ยนแปลงจากโปรแกรมภายนอก"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "สร้างแฟ้มสำรองไม่สำเร็จ"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "เครือข่ายท้องถิ่น"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "ไม่สามารถติดตามแฟ้มหรือไดเรกทอรี"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "เครือข่าย"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "ไม่รองรับการเข้าระบบผ่านบัญชีผู้ใช้"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "โฮสต์ปิดการเชื่อมต่อ"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "ไม่สามารถเปิดการเชื่อมต่อเพื่อรับส่งข้อมูล บางทีไฟร์วอลล์ของคุณอาจปิดกั้นไว้"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "การเชื่อมต่อเพื่อรับส่งข้อมูลถูกปิด"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "ปฏิบัติการล้มเหลว"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "ไม่มีที่ว่างเหลือในเซิร์ฟเวอร์"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "ไม่รองรับปฏิบัติการนี้"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "ไม่ได้รับอนุญาต"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "ได้รับชนิดของเพจที่ไม่รู้จัก"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "ชื่อแฟ้มใช้ไม่ได้"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "ได้รับคำตอบที่ใช้ไม่ได้"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "การส่งข้อมูลขาดตอน"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "ไม่สามารถเชื่อมต่อไปยังโฮสต์"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "กรุณาป้อนรหัสผ่านสำหรับ ftp ของผู้ใช้ %s ที่ %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "กรุณาป้อนรหัสผ่านสำหรับ ftp ที่ %s"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "กล่องโต้ตอบรหัสผ่านถูกยกเลิก"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp ที่ %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp ในนาม %s ที่ %s"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "แฟ้มเป็นไดเรกทอรี"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "ยังไม่รองรับการสำรองแฟ้ม"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "ชื่อแฟ้มยาวเกินไป"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "ชื่อแฟ้มปลายทางใช้ไม่ได้"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: มีแฟ้มหรือไดเรกทอรีอยู่ก่อนแล้ว"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: ไม่มีแฟ้มหรือไดเรกทอรีดังกล่าว"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: ชื่อแฟ้มใช้ไม่ได้"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: ไม่รองรับ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "กล้องดิจิทัล (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "กล้อง %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "เครื่องเล่นเพลง %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "กล้อง"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "เครื่องเล่นเพลง"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "ไม่ได้ระบุอุปกรณ์"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "ไม่สามารถสร้างบริบทสำหรับ gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "เกิดข้อผิดพลาดขณะสร้างอ็อบเจกต์กล้องถ่ายรูป"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "เกิดข้อผิดพลาดขณะโหลดข้อมูลอุปกรณ์"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "เกิดข้อผิดพลาดขณะหาข้อมูลอุปกรณ์"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "เกิดข้อผิดพลาดขณะอ่านข้อมูลอุปกรณ์"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "เกิดข้อผิดพลาดขณะกำหนดค่าพอร์ตสื่อสารของกล้องถ่ายรูป"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "เกิดข้อผิดพลาดขณะตั้งค่าเริ่มต้นของกล้องถ่ายรูป"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "การเมานท์ gphoto2 ที่ %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "ไม่ได้ระบุกล้องถ่ายรูป"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "เกิดข้อผิดพลาดขณะสร้างอ็อบเจกต์แฟ้ม"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "เกิดข้อผิดพลาดขณะหยิบแฟ้มมาใช้"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "เกิดข้อผิดพลาดขณะอ่านข้อมูลจากแฟ้ม"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "ตัวระบุไอคอน '%s' ผิดรูปแบบ"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "เกิดข้อผิดพลาดขณะเลื่อนตำแหน่งในสตรีมที่กล้องถ่ายรูป %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "ไม่ใช่ไดเรกทอรี"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "ดึงรายชื่อโฟลเดอร์ไม่สำเร็จ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "ดึงรายชื่อแฟ้มไม่สำเร็จ"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "เกิดข้อผิดพลาดขณะสร้างไดเรกทอรี"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "มีชื่อซ้ำอยู่ก่อนแล้ว"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "ชื่อใหม่ยาวเกินไป"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "เกิดข้อผิดพลาดขณะเปลี่ยนชื่อไดเรกทอรี"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "เกิดข้อผิดพลาดขณะเปลี่ยนชื่อแฟ้ม"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "ไดเรกทอรี '%s' ไม่ว่าง"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "เกิดข้อผิดพลาดขณะลบไดเรกทอรี"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "เกิดข้อผิดพลาดขณะลบแฟ้ม"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "ไม่สามารถเขียนลงในไดเรกทอรี"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "ไม่สามารถสร้างแฟ้มใหม่เพื่อเขียนต่อท้าย"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "ไม่สามารถอ่านแฟ้มที่จะเขียนต่อท้าย"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "ไม่สามารถอ่านข้อมูลจากแฟ้มที่จะเขียนต่อท้าย"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "เกิดข้อผิดพลาดขณะเขียนแฟ้ม"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "ไม่รองรับ (ไม่ใช่ไดเรกทอรีเดียวกัน)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "ไม่รองรับ (ต้นทางเป็นไดเรกทอรี, ปลายทางเป็นไดเรกทอรี)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "ไม่รองรับ (ต้นทางเป็นไดเรกทอรี, ปลายทางเป็นแฟ้มที่มีอยู่)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "ไม่รองรับ (ต้นทางเป็นแฟ้ม, ปลายทางเป็นไดเรกทอรี)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "ข้อผิดพลาดของลูกข่าย HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (รหัสอักขระผิดรูปแบบ)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "ไม่รองรับการแจ้งเหตุไดเรกทอรี"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "เครือข่ายวินโดวส์"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "หน้าต่างติดตามตำแหน่งในเครือข่าย"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s ที่ %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "ไม่มีส่วนรองรับ USB กรุณาติดต่อผู้จัดแจกซอฟต์แวร์ของคุณ"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "การเชื่อมต่อไปยังอุปกรณ์ถูกตัดขาด"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "อุปกรณ์ต้องการซอฟต์แวร์รุ่นใหม่"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "โปรแกรม ssh จบการทำงานกะทันหัน"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "ไม่รู้จักชื่อโฮสต์"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "ไม่มีเส้นทางไปยังโฮสต์"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "เซิร์ฟเวอร์ปฏิเสธการเชื่อมต่อ"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "การตรวจสอบกุญแจสำหรับโฮสต์ไม่ผ่าน"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ไม่สามารถ spawn โปรแกรม ssh"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ไม่สามารถ spawn โปรแกรม ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "หมดเวลาขณะเข้าระบบ"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "กรุณาป้อนวลีรหัสผ่านสำหรับกุญแจ"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "กรุณาป้อนรหัสผ่าน"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "ไม่สามารถส่งรหัสผ่าน"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "เข้าระบบต่อไป"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "ยกเลิกการเข้าระบบ"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"ไม่รู้จักเอกลักษณ์ของคอมพิวเตอร์ (%s) ในเครือข่าย\n"
+"เหตุการณ์นี้จะเกิดเมื่อคุณเข้าระบบไปยังคอมพิวเตอร์อื่นเป็นครั้งแรก\n"
+"\n"
+"ข้อความบอกเอกลักษณ์ที่เครื่องฝั่งโน้นส่งมาคือ %s ถ้าคุณต้องการมั่นใจว่าปลอดภัยที่จะดำเนินการต่อ "
+"กรุณาติดต่อผู้ดูแลระบบ"
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "กล่องโต้ตอบเข้าระบบถูกยกเลิก"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "ไม่สามารถส่งคำยืนยันเอกลักษณ์โฮสต์"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "โพรโทคอลผิดพลาด"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp ในนาม %s ที่ %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp ที่ %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "ไม่พบคำสั่ง ssh ที่รองรับ"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "ล้มเหลว"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "ได้รับคำตอบที่ใช้ไม่ได้"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id '%s' ใช้การไม่ได้ใน OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "เกิดข้อผิดพลาดขณะสร้างแฟ้มสำรอง: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "ไม่สามารถสร้างแฟ้มชั่วคราว"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "ไม่สามารถย้ายไดเรกทอรีทับไดเรกทอรี"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "ต้องใช้รหัสผ่านในการเข้าใช้แหล่งใช้ร่วม %s ที่ %s"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "เกิดข้อผิดพลาดภายใน (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "เมาทน์แหล่งใช้ร่วมของวินโดวส์ไม่สำเร็จ"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "ไม่รองรับการเลื่อนตำแหน่งวิธีนี้"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "สร้างแฟ้มสำรองไม่สำเร็จ: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "เกิดข้อผิดพลาดขณะลบแฟ้ม: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "เกิดข้อผิดพลาดขณะย้ายแฟ้ม: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "เกิดข้อผิดพลาดขณะลบแฟ้มปลายทาง: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "ไม่สามารถย้ายไดเรกทอรีทั้งยวง"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "บริการระบบแฟ้มแหล่งใช้ร่วมของวินโดวส์"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "ต้องใช้รหัสผ่านสำหรับ %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "แหล่งใช้ร่วมของวินโดวส์ที่ %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "ไม่สามารถดึงรายชื่อแหล่งใช้ร่วมจากเซิร์ฟเวอร์"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "แฟ้มเมานท์ไม่ได้"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "ไม่ใช่แฟ้มปกติ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "บริการระบบแฟ้มในเครือข่ายของวินโดวส์"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "ไม่สามารถลบโฟลเดอร์ถังขยะได้"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "ไม่สามารถเปลี่ยนแปลงรายการในถังขยะได้"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "ถังขยะ"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "ชนิดแบ็กเอนด์ใช้ไม่ได้"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "เกิดข้อผิดพลาดขณะส่ง fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "แบ็กเอนด์ไม่รองรับการใช้จุดเชื่อมโยง"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "ข้อความ dbus ใช้ไม่ได้"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "แทนที่ดีมอนเดิม"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "ไม่ต้องเรียก fuse ทำงาน"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "ดีมอน GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "ดีมอนหลักสำหรับ GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "ลองใช้ \"%s --help\" เพื่อดูรายละเอียดเพิ่มเติม"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "ได้รับอาร์กิวเมนต์ผิดพลาดจากโพรเซสลูกที่ spawn ออกไป"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Automount ล้มเหลว: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "ตำแหน่งที่ระบุไม่ได้ถูกเมานท์"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "ไม่รองรับตำแหน่งที่ระบุ"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "ตำแหน่งถูกเมานท์ไว้ก่อนแล้ว"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "ตำแหน่งไม่สามารถเมานท์ได้"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "แผ่น CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "แผ่น CD-ROM เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "แผ่น CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "แผ่น CD-R เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "แผ่น CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "แผ่น CD-RW เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "แผ่น DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "แผ่น DVD-ROM เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "แผ่น DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "แผ่น DVD-RAM เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "แผ่น DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "แผ่น DVD-RW เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "แผ่น DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "แผ่น DVD+R เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "แผ่น DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "แผ่น DVD+RW เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "แผ่น DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "แผ่น DVD+R DL เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "แผ่น Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "แผ่น Blu-Ray เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "แผ่น Blu-Ray R"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "แผ่น Blu-Ray R เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "แผ่น Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "แผ่น Blu-Ray RW เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "แผ่น HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "แผ่น HD DVD เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "แผ่น HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "แผ่น HD DVD-R เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "แผ่น HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "แผ่น HD DVD-RW เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "แผ่น MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "แผ่น MO เปล่า"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "แผ่น"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "แผ่นเปล่า"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "ไดรว์ %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "ไดรว์ %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "ไดรว์ฟลอปปี้"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "ไดรว์ RAID แบบซอฟต์แวร์"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "ไดรว์ USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ไดรว์ ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "ไดรว์ SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "ไดรว์ไฟร์ไวร์"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "ไดรว์เทป"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "ไดรว์ CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "ไดรว์ MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "ไดรว์ SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "ไดรว์ SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "ไดรว์ Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "ไดรว์ Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb Drive"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "ไดรว์แหล่งเก็บข้อมูล"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "ไม่สามารถดันสื่อออก: มีโวลุมตั้งแต่หนึ่งโวลุมขึ้นไปในสื่อกำลังถูกใช้งานอยู่"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "แผ่นผสมเพลง/ข้อมูล"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "สื่อ %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "ข้อมูลเข้ารหัสลับ %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: เกิดข้อผิดพลาดขณะเปิดแฟ้ม: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, เกิดข้อผิดพลาดขณะเขียน stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: เกิดข้อผิดพลาดขณะอ่าน: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: เกิดข้อผิดพลาดขณะปิด: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - แสดงเนื้อหาของตำแหน่งต่างๆ ต่อกันออกทางเอาต์พุตมาตรฐาน"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"ต่อเนื้อหาของแฟ้มต่างๆ ที่ตำแหน่งที่ระบุเข้าด้วยกัน แล้วพิมพ์ออกทางเอาต์พุตมาตรฐาน "
+"ทำงานคล้ายกับโปรแกรม cat ดั้งเดิม เพียงแต่ใช้ตำแหน่งของ gvfs แทนแฟ้มในเครื่อง ตัวอย่างเช่น "
+"คุณสามารถใช้ตำแหน่งในลักษณะ smb://server/resource/file.txt ได้"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"หมายเหตุ: คุณสามารถส่งผ่านไปป์ต่อให้คำสั่ง cat ได้ ถ้าต้องการใช้ตัวเลือกการจัดรูปแบบบางอย่าง "
+"เช่น -n, -T และอื่นๆ"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: ไม่ได้ระบุตำแหน่ง"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: เกิดข้อผิดพลาดขณะเปิดตำแหน่ง: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: เกิดข้อผิดพลาดขณะเรียกโปรแกรม: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - เปิดแฟ้มต่างๆ ด้วยโปรแกรมที่ลงทะเบียนไว้"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "เปิดแฟ้มด้วยโปรแกรมปริยายที่ลงทะเบียนไว้สำหรับจัดการแฟ้มชนิดนั้นๆ"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (ในถังขยะ)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "ไม่สามารถลบขยะ"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "ไม่รองรับการแจ้งเหตุไดเรกทอรีถังขยะ"
+
+#~ msgid "Error listing folders to figure out ignore prefix"
+#~ msgstr "เกิดข้อผิดพลาดขณะไล่เรียงโฟลเดอร์เพื่อหาส่วนหน้าที่จะตัดทิ้งของชื่อแฟ้ม"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "เกิดข้อผิดพลาดขณะสร้างรายชื่อข้อมูลพอร์ต"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "เกิดข้อผิดพลาดขณะอ่านข้อมูลพอร์ตจากรายชื่อข้อมูลพอร์ต"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "ระบบแฟ้มถูกใช้งานอยู่: เปิดแฟ้มอยู่ %d แฟ้ม"
+
+#~ msgid "Error listing folders"
+#~ msgstr "เกิดข้อผิดพลาดขณะไล่เรียงโฟลเดอร์"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "เกิดข้อผิดพลาดขณะไล่เรียงแฟ้มในโฟลเดอร์"
+
+#~ msgid "File unavailable"
+#~ msgstr "ไม่มีแฟ้มอยู่"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "สื่อ %.1f kB"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "สื่อ %.1f MB"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "สื่อ %.1f GB"
+
+#~ msgid "Invalid reply from server."
+#~ msgstr "ได้รับคำตอบที่ใช้ไม่ได้จากเซิร์ฟเวอร์"
+
+#~ msgid "The file does not exist"
+#~ msgstr "ไม่มีแฟ้มดังกล่าวอยู่"
+
+#~ msgid "Audio Disc on %s"
+#~ msgstr "แผ่นเพลงที่ %s"
diff --git a/trunk/po/tr.po b/trunk/po/tr.po
new file mode 100644
index 00000000..fde3eed2
--- /dev/null
+++ b/trunk/po/tr.po
@@ -0,0 +1,1650 @@
+# Turkish translation of gvfs.
+# Copyright (C) 2008 THE gvfs'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gvfs package.
+#
+#
+# Baris Cicek <baris@teamforce.name.tr>, 2008, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-22 22:14+0200\n"
+"PO-Revision-Date: 2009-02-22 22:32+0200\n"
+"Last-Translator: Baris Cicek <baris@teamforce.name.tr>\n"
+"Language-Team: Turkish <gnome-turk@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Dosyalar farklı bağlantılar üzerinde olduğundan işlem desteklenmiyor"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Akış dosyası belirteci alınamadı"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Akış dosyası belirteci alınmadı"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "call geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info geçersiz bir değer döndürdü"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Kapsanılan bağlantı bulunamadı"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Geçersiz dosya adı %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file geçersiz bir değer döndürdü"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "İşlem iptal edildi"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Akış protokolünde hata oluştu: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Akış sonu"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Akış üzerinde atlama desteklenmiyor"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Sorgu bilgisi işlemi desteklenmiyor"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Akış üzerinde sorgu bilgisi desteklenmiyor"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Bağlanma bilgileri alınırken hata oluştu: %s"
+
+#: ../client/gvfsdaemondbus.c:567 ../client/gvfsdaemondbus.c:998
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Servise bağlanırken hata oluştu: %s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "open_icon_for_read geçersiz değer döndü"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Soket oluşturulurken hata oluştu: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Sokete bağlanırken hata oluştu: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Geçersiz dosya bilgi biçimi "
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Geçersiz öznitelik bilgi listesi içeriği"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "Avahi başlatılırken hata: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "Avahi çözümcüsü oluşturulurken hata: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" servis \"%s\" ile \"%s\" alanı üzerinde çözülürken hata"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"\"%s\" servis \"%s\" ile \"%s\" alanı üzerinde çözülürken hata. Bir ya da "
+"daha fazla TXT kaydı eksik. Gerekli anahtarlar: \"%s\"."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "\"%s\" servis \"%s\" ile \"%s\" alanı üzerinde çözülürken zaman aşımı"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "Bozuk dns-sd encoded_triple '%s'"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "GVfsIcon kodlama sürüm %d işlenemiyor"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon için girdi verisi bozuk"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "D-Bus'a bağlanırken hata oluştu: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s Dosya Sistemi Servisi"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Hata: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Kullanım: %s ---spawner dbus-id nesne_yolu"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Kullanım: %s anahtar=değer anahtar=değer ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Belirtilmiş bağlama türü yok"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s için bağlama noktası zaten çalışıyor"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "bağlama servisi başlatılırken hata"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s üzerinde /"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Makine adı belirtilmemiş"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1626 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "Geçersiz bağlama belirtimi"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Dosya mevcut değil"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "Dosya bir dizin değil"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Yazdır"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Geçiçi dizin oluşturulamadı"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1089
+#: ../daemon/gvfsbackendgphoto2.c:1998 ../daemon/gvfsbackendgphoto2.c:2717
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Böyle dosya ya da dizin yok"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2218
+msgid "Directory not empty"
+msgstr "Dizin boş değil"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Dizin üstüne dosya kopyalanamıyor"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD Oluşturucu"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2791
+msgid "File exists"
+msgstr "Dosya mevcut"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Arkayüz tarafından işlem desteklenmiyor"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Hedef yolda böyle dosya ya da dizin yoktur"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Dizin üstüne dizin kopyalanamıyor"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Hedef dosya mevcut"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Dizin iç içe kopyalanamıyor"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2371 ../daemon/gvfsbackendgphoto2.c:2580
+#: ../daemon/gvfsbackendgphoto2.c:2677 ../daemon/gvfsbackendgphoto2.c:2770
+msgid "Not supported"
+msgstr "Desteklenmiyor"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1377
+msgid "Cannot connect to the system bus"
+msgstr "Sistem veri yoluna bağlanılamıyor"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1389
+msgid "Cannot create libhal context"
+msgstr "Libhal bağlamı oluşturulamıyor"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1402
+msgid "Cannot initialize libhal"
+msgstr "Libhal başlatılamıyor"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Sürücü belirtilmemiş"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "%s sürücüsü bulunamıyor"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Sürücü %s ses dosyaları içermiyor"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda bağı %s üzerinde"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Ses Diski"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1630
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Dosya sistemi meşgul: %d açık dosya"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "%2$s sürücüsü üzerinde %1$s dosyası yok"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "%s sürücüsünde 'paranoia' kaynaklı hata oluştu"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "%s sürücüsünde akışta atlama hatası"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1686
+#, c-format
+msgid "No such file"
+msgstr "Böyle dosya yok"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Dosya mevcut değil ya da bir ses parçası değil"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Ses CD'si Dosya Sistemi Servisi"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Bilgisayar"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Dosya sistemi"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1678
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+msgid "Can't open directory"
+msgstr "Dizin açılamıyor"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Bağlanılabilir dosya açılamıyor"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Dahili hata: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Dosya bağlanamıyor"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Sürücüde hiçbir ortam bulunamadı"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Bağlanılabilir bir dosya değil"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Dosya bağlantısı kaldırılamıyor"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Dosya çıkartılamıyor"
+
+#: ../daemon/gvfsbackenddav.c:561 ../daemon/gvfsbackenddav.c:1693
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP Hatası: %s"
+
+#: ../daemon/gvfsbackenddav.c:578
+msgid "Could not parse response"
+msgstr "Cevap ayrıştırılamadı"
+
+#: ../daemon/gvfsbackenddav.c:587
+msgid "Empty response"
+msgstr "Boş cevap"
+
+#: ../daemon/gvfsbackenddav.c:595
+msgid "Unexpected reply from server"
+msgstr "Sunucudan beklenilmeyen yanıt"
+
+#: ../daemon/gvfsbackenddav.c:1214 ../daemon/gvfsbackenddav.c:1833
+msgid "Response invalid"
+msgstr "Geçersiz cevap"
+
+#: ../daemon/gvfsbackenddav.c:1357
+msgid "WebDAV share"
+msgstr "WebDAV paylaşımı"
+
+#: ../daemon/gvfsbackenddav.c:1359
+#, c-format
+msgid "Enter password for %s"
+msgstr "%s için parolayı girin"
+
+#: ../daemon/gvfsbackenddav.c:1362
+msgid "Please enter proxy password"
+msgstr "Lütfen vekil sunucu parolasını girin"
+
+#: ../daemon/gvfsbackenddav.c:1697 ../daemon/gvfsbackenddav.c:1701
+msgid "Not a WebDAV enabled share"
+msgstr "Paylaşımı etkinleştirilmiş bir WebDAV yok"
+
+#: ../daemon/gvfsbackenddav.c:1729
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV %s üzerinde"
+
+#: ../daemon/gvfsbackenddav.c:1789 ../daemon/gvfsbackenddav.c:1862
+msgid "Could not create request"
+msgstr "İstek oluşturulamadı"
+
+#: ../daemon/gvfsbackenddav.c:1925 ../daemon/gvfsbackenddav.c:2178
+#: ../daemon/gvfsbackenddav.c:2289 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3708
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Hedef dosya zaten mevcut"
+
+#: ../daemon/gvfsbackenddav.c:1998 ../daemon/gvfsbackendsftp.c:2941
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Dosya harici olarak değiştirilmiş"
+
+#: ../daemon/gvfsbackenddav.c:2029 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Yedek dosyası oluşturma başarısız oldu"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "Yerel Ağ"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "Dosya ya da dizin izlenemiyor."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "Ağ"
+
+#: ../daemon/gvfsbackendftp.c:254
+msgid "Accounts are unsupported"
+msgstr "Hesaplar desteklenmiyor"
+
+#: ../daemon/gvfsbackendftp.c:258
+msgid "Host closed connection"
+msgstr "Makine bağlantıyı kapattı"
+
+#: ../daemon/gvfsbackendftp.c:262
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Veri bağlantısı açılamıyor. Güvenlik duvarınız bunu engelliyor olabilir mi?"
+
+#: ../daemon/gvfsbackendftp.c:266
+msgid "Data connection closed"
+msgstr "Veri bağlantısı kapatıldı"
+
+#: ../daemon/gvfsbackendftp.c:273 ../daemon/gvfsbackendftp.c:277
+msgid "Operation failed"
+msgstr "İşlem başarısız oldu"
+
+#: ../daemon/gvfsbackendftp.c:282
+msgid "No space left on server"
+msgstr "Sunucuda yer kalmadı"
+
+#: ../daemon/gvfsbackendftp.c:290 ../daemon/gvfsbackendsftp.c:4017
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "İşlem desteklenmiyor"
+
+#: ../daemon/gvfsbackendftp.c:294 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "İzin verilmedi"
+
+#: ../daemon/gvfsbackendftp.c:298
+msgid "Page type unknown"
+msgstr "Sayfa türü bilinmiyor"
+
+#: ../daemon/gvfsbackendftp.c:302 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Geçersiz dosya adı"
+
+#: ../daemon/gvfsbackendftp.c:306 ../daemon/gvfsbackendftp.c:388
+#: ../daemon/gvfsbackendftp.c:413 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Geçersiz cevap"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "bozuk iletişim"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Makineye bağlanılamadı"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "%2$s üzerindeki %1$s olarak ftp için parola girin"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "%s üzerindeki ftp için parola girin"
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Parola penceresi iptal edildi"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "%s üzerinde ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "%s olarak %s üzerinde ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3699
+msgid "File is directory"
+msgstr "Dosya bir dizin"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+#: ../daemon/gvfsbackendsftp.c:2802
+msgid "backups not supported yet"
+msgstr "yedekler henüz desteklenmiyor"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "dosya ismi çok uzun"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Geçersiz hedef dosya adı"
+
+#: ../daemon/gvfsbackendgphoto2.c:492
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Dizin ya da dosya mevcut"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Böyle bir dosya ya da dizin yok"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Geçersiz dosya ismi"
+
+#: ../daemon/gvfsbackendgphoto2.c:511
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Desteklenmiyor"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:684
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Dijital Fotoğraf Makinesi (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:832 ../monitor/gphoto2/ggphoto2volume.c:179
+#, c-format
+msgid "%s Camera"
+msgstr "%s Fotoğraf Makinası"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:174
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s Ses Çalıcısı"
+
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:188
+msgid "Camera"
+msgstr "Fotoğraf Makinası"
+
+#: ../daemon/gvfsbackendgphoto2.c:846 ../monitor/gphoto2/ggphoto2volume.c:186
+msgid "Audio Player"
+msgstr "Ses Çalıcısı"
+
+#: ../daemon/gvfsbackendgphoto2.c:1417
+msgid "No device specified"
+msgstr "Hiçbir aygıt belirtilmedi"
+
+#: ../daemon/gvfsbackendgphoto2.c:1434
+msgid "Cannot create gphoto2 context"
+msgstr "gphoto2 bağlamı oluşturulamıyor"
+
+#: ../daemon/gvfsbackendgphoto2.c:1444
+msgid "Error creating camera"
+msgstr "Fotograf makinesi oluşturulurken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1457 ../daemon/gvfsbackendgphoto2.c:1467
+msgid "Error loading device information"
+msgstr "Aygıt bilgisi yüklenirken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1479
+msgid "Error looking up device information"
+msgstr "Aygıt bilgisine bakılırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1489
+msgid "Error getting device information"
+msgstr "Aygıt bilgisi alınırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1502
+msgid "Error setting up camera communications port"
+msgstr "Fotograf makinesi iletişim portu ayarlanırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1513
+msgid "Error initializing camera"
+msgstr "Fotograf makinesi başlatılırken hata"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1527
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 bağı %s üzerinde"
+
+#: ../daemon/gvfsbackendgphoto2.c:1602
+msgid "No camera specified"
+msgstr "Hiçbir fotograf makinesi belirtilmedi"
+
+#: ../daemon/gvfsbackendgphoto2.c:1694
+msgid "Error creating file object"
+msgstr "Dosya nesnesi oluşturulurken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1709
+msgid "Error getting file"
+msgstr "Dosya alınırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1719
+msgid "Error getting data from file"
+msgstr "Dosyadan veri alınırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1776
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Bozuk simge belirteci '%s'"
+
+#: ../daemon/gvfsbackendgphoto2.c:1852 ../daemon/gvfsbackendgphoto2.c:3041
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Fotograf makinesi %s üzerinde akış içine atlanırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:1992 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Bir dizin değil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2025
+msgid "Failed to get folder list"
+msgstr "Klasör listesi alma başarısız oldu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2091
+msgid "Failed to get file list"
+msgstr "Dosya listesi alınırken başarısız olundu"
+
+#: ../daemon/gvfsbackendgphoto2.c:2383
+msgid "Error creating directory"
+msgstr "Dizin oluşturuken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592
+msgid "Name already exists"
+msgstr "İsim zaten mevcut"
+
+#: ../daemon/gvfsbackendgphoto2.c:2603 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "New name too long"
+msgstr "Yeni isim çok uzun"
+
+#: ../daemon/gvfsbackendgphoto2.c:2613 ../daemon/gvfsbackendgphoto2.c:3243
+msgid "Error renaming dir"
+msgstr "Dizin tekrar adlandırılırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2626 ../daemon/gvfsbackendgphoto2.c:3256
+msgid "Error renaming file"
+msgstr "Dosya yeniden adlandırılırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Dizin '%s' boş değil"
+
+#: ../daemon/gvfsbackendgphoto2.c:2701
+msgid "Error deleting directory"
+msgstr "Dizin silinirken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2727
+msgid "Error deleting file"
+msgstr "Dosya silinirken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:2780
+msgid "Can't write to directory"
+msgstr "Dizine yazılamıyor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2827
+msgid "Cannot allocate new file to append to"
+msgstr "Sonuna eklemek için yeni dosya ayrılamıyor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot read file to append to"
+msgstr "Sonuna eklemek için dosya okunamıyor"
+
+#: ../daemon/gvfsbackendgphoto2.c:2853
+msgid "Cannot get data of file to append to"
+msgstr "Sonuna eklemek için dosyanın verisi alınamıyor"
+
+#: ../daemon/gvfsbackendgphoto2.c:3140
+msgid "Error writing file"
+msgstr "Dosyaya yazılırken hata"
+
+#: ../daemon/gvfsbackendgphoto2.c:3188
+msgid "Not supported (not same directory)"
+msgstr "Desteklenmiyor (aynı dizin değil)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3200
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Desteklenmiyor (src bir dizin, dst bir dizin)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3208
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Desteklenmiyor (src bir dizin, dst mevcut bir dosya)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3220
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Desteklenmiyor (src bir dosya, dst bir dizin)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP İstemci Hatası: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr ".(geçersiz kodlama)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Dizin bildirimi desteklenmiyor"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows Ağı"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "Ağ Konum İzleyici"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%2$s üzerinde %1$s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB desteği eksik. Lütfen yazılım üreticinizle bağlantıya geçin"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Aygıtla bağlantı kayboldu"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Aygıt yazılım güncellemesi gerektiriyor"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh programından beklenilmeyen çıkış"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Makine adı bilinmiyor"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Makineye ulaşılamıyor"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Bağlantı sunucu tarafından reddedildi"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Makine anahtarının onaylanması başarısız oldu"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "ssh programı yeniden başlatılamadı"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "ssh programı yeniden başlatılamadı: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Giriş yapılırken zaman aşımına uğradı"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Anahtar için parola metnini girin"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Parolayı girin"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Parola gönderilemiyor"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Gene de Giriş Yap"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Girişi İptal Et"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Uzaktaki bilgisayarın (%s) kimliği bilinmiyor.\n"
+"Bu bir bilgisayara ilk kez giriş yaptığınızda olur.\n"
+"\n"
+"Uzaktaki bilgisayardan gelen kimlik ise %s. Eğer devam etmek için tamamen "
+"güvenli olduğundan emin olmak istiyorsanız, sistem yöneticinizle bağlantıya "
+"geçin."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Giriş penceresi iptal edildi"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Makine kimlik onayı gönderilemiyor"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Protokol hatası"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "%2$s üzerindeki %1$s için sftp"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "%s üzerinde sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Desteknelen ssh komut komutu bulunamadı"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Başarısız"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2704
+#: ../daemon/gvfsbackendsftp.c:2716 ../daemon/gvfsbackendsftp.c:2774
+#: ../daemon/gvfsbackendsftp.c:2816 ../daemon/gvfsbackendsftp.c:2993
+#: ../daemon/gvfsbackendsftp.c:3018 ../daemon/gvfsbackendsftp.c:3073
+#: ../daemon/gvfsbackendsftp.c:3130 ../daemon/gvfsbackendsftp.c:3401
+#: ../daemon/gvfsbackendsftp.c:3468 ../daemon/gvfsbackendsftp.c:3597
+#: ../daemon/gvfsbackendsftp.c:3632 ../daemon/gvfsbackendsftp.c:3660
+#: ../daemon/gvfsbackendsftp.c:3768 ../daemon/gvfsbackendsftp.c:3822
+#: ../daemon/gvfsbackendsftp.c:3856 ../daemon/gvfsbackendsftp.c:3890
+#: ../daemon/gvfsbackendsftp.c:3905 ../daemon/gvfsbackendsftp.c:3920
+#: ../daemon/gvfsbackendsftp.c:3998
+msgid "Invalid reply received"
+msgstr "Geçersiz cevap alındı"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead içinde geçersiz icon_id '%s'"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Yedek dosya oluşturulurken hata: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2878
+msgid "Unable to create temporary file"
+msgstr "Geçici dosya oluşturulamadı"
+
+#: ../daemon/gvfsbackendsftp.c:3694 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Dizin üstüne dizin taşınamıyor"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "%2$s üzerinde %1$s paylaşımı için parola gerekli"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Dahili Hata (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Windows paylaşımı bağlama başarısız oldu"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Atlama türü desteklenmiyor"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Yedek dosyası oluşturma başarısız: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Dosya silinirken hata: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Dosya taşınırken hata: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Hedef dosya silinirken hata: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Dizin iç içe taşınamıyor"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows Paylaşımlar Dosya Sistemi Servisi"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s için parola gerekli"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s üzerindeki Windows paylaşımları"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Sunucudan paylaşım listesi alınırken başarısız olundu"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Dosya bağlanılabilir değil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Düzenli bir dosya değil"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows Ağ Dosya Sistemi Servisi"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+msgid "The trash folder may not be deleted"
+msgstr "Çöp klasörü silinmemeli"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+msgid "Items in the trash may not be modified"
+msgstr "Çöp içerisindeki öğeler değiştirilmemeli"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Çöp"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Geçersiz arkayüz türü"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "fd gönderilirken hata: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Arkayüz tarafından sembolik bağlar desteklenmiyor"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Geçersiz dbus mesajı"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Eski servisin yerine kondu."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "fuse'ü başlatma."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS Servisi"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS için ana servis"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Daha fazla bilgi için \"%s --help\" deneyin."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Yeniden başlatılan alt süreçler için geçersiz parametreler"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Kendiliğinden bağlama başarısız oldu: %s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Belirtilen konum bağlanmamış"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Belirtilen konum desteklenmiyor"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Konum zaten bağlanmış"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Konum bağlanılabilir değil"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Boş CD-ROM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Boş CD-R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Boş CD-RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Boş DVD-ROM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Boş DVD-RAM Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Boş DVD-RW·Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Boş DVD+R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Boş DVD+RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Boş DVD+R DL Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Boş Blu-Ray Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Boş Blu-Ray R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Boş Blu-Ray RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Boş HD DVD Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Boş HD DVD-R Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Boş HD DVD-RW Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Boş MO Diski"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Disk"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Boş Disk"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s Sürücü"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Disket Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Yazılımsal RAID Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Bant Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash Sürücüsü"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Depolama Aygıtı Sürücü"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Ortamı çıkartma başarısız; ortam üzerinde bir ya da daha fazla sistem meşgul."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "% 1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "% 1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "% 1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Karışık Ses/Veri Diski"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s Ortam"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s Şifreli Veri"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: dosya açılırken hata: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, stdout'a yazılırken hata"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: okuma hatası: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:kapatma hatası: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "KONUM... - standart çıktıya KONUMLAR ile '-' birleştirilir."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Konumlardaki dosyalar birleştirilir ve standart çıktıya yazılır. Geleneksel "
+"cat aracı gibi çalışır, fakat yerel dosyalar yerine gvfs yeri kullanılır: "
+"örneğin yer olarak birleştirmede smb://sunucu/kaynak/dosya.txt gibi bir şeyi "
+"kullanabilirsiniz."
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Not: eğer biçimleme seçenekleri -n, -T ya da diğerlerine ihtiyaç "
+"duyuyorsanız sadece cat'e borulayın."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: eksik konumlar"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: konum açılırken hata: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: uygulama başlatılırken hata: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "DOSYALAR... - kayıtlı uygulamayla DOSYALAR açılır."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Dosya türünü işlemek için kayıtlı öntanımlı uygulama ile dosya(lar) açılır."
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (çöpte)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "Çöp silinemiyor"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "Çöp dizin bildirimi desteklenmiyor"
+
+#~ msgid "File unavailable"
+#~ msgstr "Dosya mevcut değil"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB Ortam"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB Ortam"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "% 1f GB Ortam"
diff --git a/trunk/po/uk.po b/trunk/po/uk.po
new file mode 100644
index 00000000..b56666d4
--- /dev/null
+++ b/trunk/po/uk.po
@@ -0,0 +1,1558 @@
+# translation of gvfs to Ukrainian
+# Copyright (C) Free Software Foundation
+# This file is distributed under the same license as the gvfs package.
+#
+# Maxim Dziumanenko <dziumanenko@gmail.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-21 19:47+0000\n"
+"PO-Revision-Date: 2008-09-21 14:54+0200\n"
+"Last-Translator: Maxim Dziumanenko <dziumanenko@gmail.com>\n"
+"Language-Team: Russian <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Дія не підтримується, файли на різних точках монтування"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Функція get_info повернула неправильне значення"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Функція query_info повернула неправильне значення"
+
+#: ../client/gdaemonfile.c:894
+msgid "Couldn't get stream file descriptor"
+msgstr "Не вдається отримати опис файлу потоку"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+msgid "Invalid return value from open"
+msgstr "Функція open повернула неправильне значення"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+msgid "Didn't get stream file descriptor"
+msgstr "Дескриптор файлу потоку не був отриманий"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Функція call повернула неправильне значення"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Функція get_filesystem_info повернула неправильне значення"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Не вдається знайти точку монтування"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Неправильна назва файлу %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Функція query_filesystem_info повернула неправильне значення"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Отримано неправильне значення від функції monitor_dir"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Отримано неправильне значення від функції monitor_file"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Помилка у протоколі потоку: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Кінець потоку"
+
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:772
+#: ../daemon/gvfsbackendobexftp.c:793 ../daemon/gvfsbackendobexftp.c:912
+#: ../daemon/gvfsbackendobexftp.c:1049 ../daemon/gvfsbackendobexftp.c:1113
+#: ../daemon/gvfsbackendobexftp.c:1250 ../daemon/gvfsbackendobexftp.c:1277
+#: ../daemon/gvfsbackendobexftp.c:1336 ../daemon/gvfsbackendobexftp.c:1358
+#: ../daemon/gvfsbackendobexftp.c:1418 ../daemon/gvfsbackendobexftp.c:1437
+#: ../daemon/gvfsbackendsmb.c:1087 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "Дія була перервана"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Пошук у потоці не підтримується"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Операція запиту інформації не підтримується"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Запит інформації не підтримується у потоці"
+
+#: ../client/gdaemonvfs.c:757
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Помилка при отриманні інформації про монтування: %s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Помилка при підключенні до служби: %s"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Помилка при створенні сокета: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Помилка при підключенні до сокету: %s"
+
+#: ../common/gvfsdaemonprotocol.c:515
+msgid "Invalid file info format"
+msgstr "Неправильний формат інформації про файл"
+
+#: ../common/gvfsdaemonprotocol.c:532
+msgid "Invalid attribute info list content"
+msgstr "Неправильний зміст списку інформації про атрибути"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Помилка приєднання до D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Служба файлової системи %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Помилка: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Використання: %s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Використання: %s ключ=значення ключ=значення ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Тип монтування не вказано"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "точка монтування для %s уже запущена"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "помилка запуску служби монтування"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:963
+#: ../daemon/gvfsbackendsftp.c:1894
+#, c-format
+msgid "/ on %s"
+msgstr "/ на %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1553
+msgid "No hostname specified"
+msgstr "Назва вузла не вказана"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1456 ../daemon/gvfsbackendhttp.c:299
+#: ../daemon/gvfsbackendobexftp.c:603 ../daemon/gvfsbackendobexftp.c:614
+#: ../daemon/gvfsbackendsmb.c:623
+msgid "Invalid mount spec"
+msgstr "Неправильна специфікація монтування"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:345
+#: ../daemon/gvfsbackendftp.c:2101 ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804 ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042 ../daemon/gvfsbackendsmbbrowse.c:1116
+#, c-format
+msgid "File doesn't exist"
+msgstr "Файл не існує"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:912 ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "Цей файл не є каталогом"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Записати"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Не вдається створити тимчасовий каталог"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1098
+#: ../daemon/gvfsbackendgphoto2.c:1987 ../daemon/gvfsbackendgphoto2.c:2706
+#, c-format
+msgid "No such file or directory"
+msgstr "Немає такого файлу чи каталогу"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2043
+msgid "Directory not empty"
+msgstr "Каталог не порожній"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "Не вдається скопіювати файл поверх каталогу"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Створення CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2780
+msgid "File exists"
+msgstr "Файл існує"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobpull.c:173 ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135 ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149 ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119 ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150 ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122 ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Дія не підтримується драйвером"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Немає такого файлу чи каталогу у шляху призначення"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "Не вдається скопіювати каталог поверх каталогу"
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "Файл призначення вже існує"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "Не вдається скопіювати каталог рекурсивно"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendgphoto2.c:2360
+#: ../daemon/gvfsbackendgphoto2.c:2569 ../daemon/gvfsbackendgphoto2.c:2666
+#: ../daemon/gvfsbackendgphoto2.c:2759
+msgid "Not supported"
+msgstr "Не підтримується"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1403
+msgid "Cannot connect to the system bus"
+msgstr "Не вдається з'єднатися з системною шиною"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Cannot create libhal context"
+msgstr "Не вдається з'єднатися з контекстом libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Cannot initialize libhal"
+msgstr "Не вдається ініціалізувати libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Пристрій не вказано"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Не вдається найти пристрій %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Пристрій %s не містить звукових файлів"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "підключення cdda до %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Звуковий диск"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1656
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Файлова система зайнята: %d відкритий файл"
+msgstr[1] "Файлова система зайнята: %d відкритих файли"
+msgstr[2] "Файлова система зайнята: %d відкритих файлів"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Немає такого файлу %s на пристрої %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Помилка програми \"paranoia\" на пристрої %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Помилка пошуку у потоці на пристрої %s"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1713
+#, c-format
+msgid "No such file"
+msgstr "Немає такого файлу"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Файл не існує або не є звуковою доріжкою"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Служба файлової системи Audio CD"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Комп'ютер"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Файлова система"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1705
+#: ../daemon/gvfsbackendobexftp.c:758 ../daemon/gvfsbackendsmb.c:666
+#: ../daemon/gvfsbackendtrash.c:678 ../daemon/gvfsbackendtrash.c:1786
+msgid "Can't open directory"
+msgstr "Не вдається відкрити каталог"
+
+#: ../daemon/gvfsbackendcomputer.c:594 ../daemon/gvfsbackendcomputer.c:732
+msgid "Can't open mountable file"
+msgstr "Не вдається відкрити файл, що монтується"
+
+#: ../daemon/gvfsbackendcomputer.c:780 ../daemon/gvfsbackendsftp.c:1037
+#, c-format
+msgid "Internal error: %s"
+msgstr "Внутрішня помилка: %s"
+
+#: ../daemon/gvfsbackendcomputer.c:812 ../daemon/gvfsbackendcomputer.c:929
+msgid "Can't mount file"
+msgstr "Не вдається змонтувати файл"
+
+#: ../daemon/gvfsbackendcomputer.c:824
+msgid "No media in the drive"
+msgstr "У пристрої відсутній диск"
+
+#: ../daemon/gvfsbackendcomputer.c:881 ../daemon/gvfsbackendcomputer.c:972
+#: ../daemon/gvfsbackendcomputer.c:1072
+msgid "Not a mountable file"
+msgstr "Файл не є файлом для підключення"
+
+#: ../daemon/gvfsbackendcomputer.c:987
+msgid "Can't unmount file"
+msgstr "Не вдається відключити файл"
+
+#: ../daemon/gvfsbackendcomputer.c:1103
+msgid "Can't eject file"
+msgstr "Не вдається витягнути файл"
+
+#: ../daemon/gvfsbackenddav.c:503 ../daemon/gvfsbackenddav.c:1523
+#: ../daemon/gvfsbackendhttp.c:245
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Помилка HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:520
+msgid "Could not parse response"
+msgstr "Не вдається розібрати відповідь"
+
+#: ../daemon/gvfsbackenddav.c:529
+msgid "Empty response"
+msgstr "Відповідь порожня"
+
+#: ../daemon/gvfsbackenddav.c:537
+msgid "Unexpected reply from server"
+msgstr "Неочікувана відповідь від сервера"
+
+#: ../daemon/gvfsbackenddav.c:1156 ../daemon/gvfsbackenddav.c:1658
+msgid "Response invalid"
+msgstr "Неправильна відповідь"
+
+#: ../daemon/gvfsbackenddav.c:1299
+msgid "WebDAV share"
+msgstr "Ресурс WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1301
+#, c-format
+msgid "Enter password for %s"
+msgstr "Введіть пароль для %s"
+
+#: ../daemon/gvfsbackenddav.c:1304
+msgid "Please enter proxy password"
+msgstr "Введіть пароль проксі-сервера"
+
+#: ../daemon/gvfsbackenddav.c:1527 ../daemon/gvfsbackenddav.c:1531
+msgid "Not a WebDAV enabled share"
+msgstr "Не є ресурсом WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1554
+#, c-format
+msgid "WebDAV on %s"
+msgstr "Ресурс WebDAV на %s"
+
+#: ../daemon/gvfsbackenddav.c:1614 ../daemon/gvfsbackenddav.c:1687
+msgid "Could not create request"
+msgstr "Не вдається створити запит"
+
+#: ../daemon/gvfsbackenddav.c:1750 ../daemon/gvfsbackenddav.c:2003
+#: ../daemon/gvfsbackenddav.c:2114 ../daemon/gvfsbackendftp.c:1699
+#: ../daemon/gvfsbackendftp.c:2365 ../daemon/gvfsbackendsftp.c:3559
+#: ../daemon/gvfsbackendsmb.c:1822
+msgid "Target file already exists"
+msgstr "Файл призначення вже існує"
+
+#: ../daemon/gvfsbackenddav.c:1823 ../daemon/gvfsbackendsftp.c:2807
+#: ../daemon/gvfsbackendsmb.c:1056
+msgid "The file was externally modified"
+msgstr "Файл був змінений зовні"
+
+#: ../daemon/gvfsbackenddav.c:1854 ../daemon/gvfsbackendsmb.c:1092
+#: ../daemon/gvfsbackendsmb.c:1839
+msgid "Backup file creation failed"
+msgstr "Помилка при створенні резервної копії файлу"
+
+#. TODO: Name
+#: ../daemon/gvfsbackenddnssd.c:433
+msgid "dns-sd"
+msgstr "dns-sd"
+
+#: ../daemon/gvfsbackenddnssd.c:669 ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "Не вдається стежити за станом файлу чи каталогу."
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:687
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:688 ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814 ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "Мережа"
+
+#: ../daemon/gvfsbackendftp.c:236
+msgid "Accounts are unsupported"
+msgstr "Облікові записи не підтримуються"
+
+#: ../daemon/gvfsbackendftp.c:240
+msgid "Host closed connection"
+msgstr "Вузол закрив з'єднання"
+
+#: ../daemon/gvfsbackendftp.c:244
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr ""
+"Не вдається встановити з'єднання даних. Перевірте параметри брандмауера."
+
+#: ../daemon/gvfsbackendftp.c:248
+msgid "Data connection closed"
+msgstr "З'єднання даних закрите"
+
+#: ../daemon/gvfsbackendftp.c:255 ../daemon/gvfsbackendftp.c:259
+msgid "Operation failed"
+msgstr "Помилка операції"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "No space left on server"
+msgstr "На сервері не залишилось вільного місця"
+
+#: ../daemon/gvfsbackendftp.c:272 ../daemon/gvfsbackendsftp.c:3868
+msgid "Operation unsupported"
+msgstr "Дія підтримується"
+
+#: ../daemon/gvfsbackendftp.c:276 ../daemon/gvfsbackendsftp.c:289
+msgid "Permission denied"
+msgstr "Доступ заборонено"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "Page type unknown"
+msgstr "Невідомий тип сторінки"
+
+#: ../daemon/gvfsbackendftp.c:284 ../daemon/gvfsbackendftp.c:2211
+msgid "Invalid filename"
+msgstr "Неправильна назва файлу"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendftp.c:364
+#: ../daemon/gvfsbackendftp.c:393 ../daemon/gvfsbackendftp.c:412
+#: ../daemon/gvfsbackendftp.c:425 ../daemon/gvfsbackendftp.c:817
+msgid "Invalid reply"
+msgstr "Неправильна відповідь"
+
+#: ../daemon/gvfsbackendftp.c:532
+msgid "broken transmission"
+msgstr "помилка при передачі"
+
+#: ../daemon/gvfsbackendftp.c:677 ../daemon/gvfsbackendftp.c:837
+msgid "Could not connect to host"
+msgstr "Не вдається з'єднатися з вузлом"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1337
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Введіть пароль для ftp на %s"
+
+#: ../daemon/gvfsbackendftp.c:1362 ../daemon/gvfsbackendsftp.c:874
+msgid "Password dialog cancelled"
+msgstr "Діалог вводу паролю перервано"
+
+#: ../daemon/gvfsbackendftp.c:1441
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp на %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1445
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "ftp як %s на %s"
+
+#: ../daemon/gvfsbackendftp.c:1529 ../daemon/gvfsbackendsftp.c:1958
+#: ../daemon/gvfsbackendsftp.c:3550
+msgid "File is directory"
+msgstr "Файл є каталогом"
+
+#: ../daemon/gvfsbackendftp.c:1751 ../daemon/gvfsbackendftp.c:2326
+msgid "backups not supported yet"
+msgstr "резервні копії ще не підтримуються"
+
+#: ../daemon/gvfsbackendftp.c:1828
+msgid "filename too long"
+msgstr "назва файлу надто довга"
+
+#: ../daemon/gvfsbackendftp.c:2345
+msgid "Invalid destination filename"
+msgstr "Неправильна назва файлу призначення"
+
+#: ../daemon/gvfsbackendgphoto2.c:501
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: каталог або файл існує"
+
+#: ../daemon/gvfsbackendgphoto2.c:508
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: файл або каталог не існує"
+
+#: ../daemon/gvfsbackendgphoto2.c:514
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: некоректна назва файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:520
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: не підтримується"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:693
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Цифрова камера (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:841 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Камера %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:844 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Звуковий програвач %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:853 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Камера"
+
+#: ../daemon/gvfsbackendgphoto2.c:855 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Звуковий програвач"
+
+#: ../daemon/gvfsbackendgphoto2.c:1325 ../daemon/gvfsbackendgphoto2.c:2014
+msgid "Failed to get folder list"
+msgstr "Помилка при отриманні списку теки"
+
+#: ../daemon/gvfsbackendgphoto2.c:1443
+msgid "No device specified"
+msgstr "Пристрій не вказано"
+
+#: ../daemon/gvfsbackendgphoto2.c:1460
+msgid "Cannot create gphoto2 context"
+msgstr "Не вдається створити контекст gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1470
+msgid "Error creating camera"
+msgstr "Помилка при створенні фотоапарату"
+
+#: ../daemon/gvfsbackendgphoto2.c:1483 ../daemon/gvfsbackendgphoto2.c:1493
+msgid "Error loading device information"
+msgstr "Помилка при завантаженні інформації про пристрій"
+
+#: ../daemon/gvfsbackendgphoto2.c:1505
+msgid "Error looking up device information"
+msgstr "Помилка при пошуку інформації про пристрій"
+
+#: ../daemon/gvfsbackendgphoto2.c:1515
+msgid "Error getting device information"
+msgstr "Помилка при отриманні інформації про пристрій"
+
+#: ../daemon/gvfsbackendgphoto2.c:1528
+msgid "Error setting up camera communications port"
+msgstr "Помилка при налаштовуванні комунікаційних портів фотоапарату"
+
+#: ../daemon/gvfsbackendgphoto2.c:1539
+msgid "Error initializing camera"
+msgstr "Помилка при ініціалізації фотоапарату"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1553
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "підключення gphoto2 на %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1628
+msgid "No camera specified"
+msgstr "Назва фотоапарату не вказано"
+
+#: ../daemon/gvfsbackendgphoto2.c:1721
+msgid "Error creating file object"
+msgstr "Помилка при створенні об'єкту файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:1736
+msgid "Error getting file"
+msgstr "Помилка при отриманні файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:1746
+msgid "Error getting data from file"
+msgstr "Помилка при отриманні даних від файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:1841 ../daemon/gvfsbackendgphoto2.c:3030
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Помилка пошуку у потоці на фотоапараті %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1981 ../daemon/gvfsbackendsmbbrowse.c:1112
+msgid "Not a directory"
+msgstr "Не є каталогом"
+
+#: ../daemon/gvfsbackendgphoto2.c:2080
+msgid "Failed to get file list"
+msgstr "Не вдається отримати список файлів"
+
+#: ../daemon/gvfsbackendgphoto2.c:2372
+msgid "Error creating directory"
+msgstr "Помилка при створенні каталогу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2581
+msgid "Name already exists"
+msgstr "Назва вже існує"
+
+#: ../daemon/gvfsbackendgphoto2.c:2592 ../daemon/gvfsbackendgphoto2.c:3221
+msgid "New name too long"
+msgstr "Назва надто довга"
+
+#: ../daemon/gvfsbackendgphoto2.c:2602 ../daemon/gvfsbackendgphoto2.c:3232
+msgid "Error renaming dir"
+msgstr "Помилка при перейменуванні каталогу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2615 ../daemon/gvfsbackendgphoto2.c:3245
+msgid "Error renaming file"
+msgstr "Помилка при перейменуванні файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2679
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Каталог '%s' не порожній"
+
+#: ../daemon/gvfsbackendgphoto2.c:2690
+msgid "Error deleting directory"
+msgstr "Помилка при видалення каталогу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2716
+msgid "Error deleting file"
+msgstr "Помилка при видалення файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2769
+msgid "Can't write to directory"
+msgstr "Не вдається записати до каталогу"
+
+#: ../daemon/gvfsbackendgphoto2.c:2816
+msgid "Cannot allocate new file to append to"
+msgstr "Не вдається створити новий файл для додавання"
+
+#: ../daemon/gvfsbackendgphoto2.c:2831
+msgid "Cannot read file to append to"
+msgstr "Не вдається прочитати файл для додавання"
+
+#: ../daemon/gvfsbackendgphoto2.c:2842
+msgid "Cannot get data of file to append to"
+msgstr "Не вдається отримати дані файлу для додавання"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Error writing file"
+msgstr "Помилка при записі до файлу"
+
+#: ../daemon/gvfsbackendgphoto2.c:3177
+msgid "Not supported (not same directory)"
+msgstr "Не підтримується (не є тим самим каталогом)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3189
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Не підтримується (src - каталог, dst - каталог)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3197
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Не підтримується (src - каталог, dst - існуючий файл)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3209
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Не підтримується (src - файл, dst - каталог)"
+
+#: ../daemon/gvfsbackendhttp.c:241
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Помилка клієнта HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:560 ../daemon/gvfsbackendsftp.c:1882
+#: ../daemon/gvfsbackendsmb.c:1319 ../daemon/gvfsbackendtrash.c:1006
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (неправильне кодування)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Сповіщення для каталогів не підтримується"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268 ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Мережа Windows"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "Локальна мережа"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "Огляд мережі"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:442 ../daemon/gvfsbackendsmb.c:528
+#: ../daemon/gvfsbackendsmb.c:1312
+#, c-format
+msgid "%s on %s"
+msgstr "%s на %s"
+
+#: ../daemon/gvfsbackendobexftp.c:699
+msgid "Connection to the device lost"
+msgstr "З'єднання з пристроєм втрачено"
+
+#: ../daemon/gvfsbackendobexftp.c:1194
+msgid "Device requires a software update"
+msgstr "Пристрій вимагає оновлення програми"
+
+#: ../daemon/gvfsbackendsftp.c:281
+msgid "ssh program unexpectedly exited"
+msgstr "Програма ssh несподівано завершилась"
+
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Hostname not known"
+msgstr "Невідома назва вузла"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "No route to host"
+msgstr "Немає маршруту до вузла"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "Connection refused by server"
+msgstr "З'єднання відхилено сервером"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Host key verification failed"
+msgstr "Помилка при перевірці сертифікату вузла"
+
+#: ../daemon/gvfsbackendsftp.c:400
+msgid "Unable to spawn ssh program"
+msgstr "Не вдається виконати програму ssh"
+
+#: ../daemon/gvfsbackendsftp.c:416
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Не вдається виконати програму ssh: %s"
+
+#: ../daemon/gvfsbackendsftp.c:528 ../daemon/gvfsbackendsftp.c:780
+msgid "Timed out when logging in"
+msgstr "Час очікування входу у систему вийшов"
+
+#: ../daemon/gvfsbackendsftp.c:858
+msgid "Enter passphrase for key"
+msgstr "Введіть ключову фразу для ключа"
+
+#: ../daemon/gvfsbackendsftp.c:860
+msgid "Enter password"
+msgstr "Введіть пароль"
+
+#: ../daemon/gvfsbackendsftp.c:921
+msgid "Can't send password"
+msgstr "Не вдається надіслати пароль"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Log In Anyway"
+msgstr "З'єднатися попри все"
+
+#: ../daemon/gvfsbackendsftp.c:929
+msgid "Cancel Login"
+msgstr "Скасувати з'єднання"
+
+#: ../daemon/gvfsbackendsftp.c:939
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Не вдається перевірити автентичність віддаленого комп'ютера (%s).\n"
+"Це зазвичай відбувається при першому з'єданні з комп'ютером.\n"
+"\n"
+"Рядок ідентифікації, переданий віддаленим комп'ютером: %s. Якщо ви хочете "
+"бути абсолютно впевнені у безпеці з'єднання з цим комп'ютером, зверніться до "
+"системного адміністратора."
+
+#: ../daemon/gvfsbackendsftp.c:959
+msgid "Login dialog cancelled"
+msgstr "Діалог вводу паролю перервано"
+
+#: ../daemon/gvfsbackendsftp.c:979
+msgid "Can't send host identity confirmation"
+msgstr "Не вдається надіслати підтвердження ідентифікації вузла"
+
+#: ../daemon/gvfsbackendsftp.c:1472 ../daemon/gvfsbackendsftp.c:1495
+msgid "Protocol error"
+msgstr "Помилка у протоколі"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1519
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp на %s"
+
+#: ../daemon/gvfsbackendsftp.c:1543
+msgid "Unable to find supported ssh command"
+msgstr "Не вдається знайти підтримувану команду ssh"
+
+#: ../daemon/gvfsbackendsftp.c:1967
+msgid "Failure"
+msgstr "Помилка"
+
+#: ../daemon/gvfsbackendsftp.c:2023 ../daemon/gvfsbackendsftp.c:2082
+#: ../daemon/gvfsbackendsftp.c:2093 ../daemon/gvfsbackendsftp.c:2149
+#: ../daemon/gvfsbackendsftp.c:2235 ../daemon/gvfsbackendsftp.c:2285
+#: ../daemon/gvfsbackendsftp.c:2331 ../daemon/gvfsbackendsftp.c:2406
+#: ../daemon/gvfsbackendsftp.c:2513 ../daemon/gvfsbackendsftp.c:2553
+#: ../daemon/gvfsbackendsftp.c:2603 ../daemon/gvfsbackendsftp.c:2672
+#: ../daemon/gvfsbackendsftp.c:2692 ../daemon/gvfsbackendsftp.c:2844
+#: ../daemon/gvfsbackendsftp.c:2869 ../daemon/gvfsbackendsftp.c:2924
+#: ../daemon/gvfsbackendsftp.c:2981 ../daemon/gvfsbackendsftp.c:3252
+#: ../daemon/gvfsbackendsftp.c:3319 ../daemon/gvfsbackendsftp.c:3448
+#: ../daemon/gvfsbackendsftp.c:3483 ../daemon/gvfsbackendsftp.c:3511
+#: ../daemon/gvfsbackendsftp.c:3619 ../daemon/gvfsbackendsftp.c:3673
+#: ../daemon/gvfsbackendsftp.c:3707 ../daemon/gvfsbackendsftp.c:3741
+#: ../daemon/gvfsbackendsftp.c:3756 ../daemon/gvfsbackendsftp.c:3771
+#: ../daemon/gvfsbackendsftp.c:3849
+msgid "Invalid reply received"
+msgstr "Отримано неправильну відповідь"
+
+#: ../daemon/gvfsbackendsftp.c:2351
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Помилка створення резервної копії файлу: %s"
+
+#: ../daemon/gvfsbackendsftp.c:2754
+msgid "Unable to create temporary file"
+msgstr "Не вдається створити тимчасовий файл"
+
+#: ../daemon/gvfsbackendsftp.c:3545 ../daemon/gvfsbackendsmb.c:1811
+msgid "Can't move directory over directory"
+msgstr "Не вдається перемістити каталог над каталогом"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:213
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Вимагається пароль для ресурсу %s на %s"
+
+#: ../daemon/gvfsbackendsmb.c:468 ../daemon/gvfsbackendsmb.c:514
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Внутрішня помилка (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:587
+msgid "Failed to mount Windows share"
+msgstr "Помилка приєднання ресурсу Windows"
+
+#: ../daemon/gvfsbackendsmb.c:735 ../daemon/gvfsbackendsmb.c:1191
+msgid "Unsupported seek type"
+msgstr "Непідтримуваний тип пошуку"
+
+#: ../daemon/gvfsbackendsmb.c:1255
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Помилка при створенні резервного файлу: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1713
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Помилка при видалення файлу: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1787
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Помилка при переміщенні файлу: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1859
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Помилка при видаленні файла призначення: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1883
+msgid "Can't recursively move directory"
+msgstr "Не вдається перемістити каталог рекурсивно"
+
+#: ../daemon/gvfsbackendsmb.c:1946
+msgid "Windows Shares Filesystem Service"
+msgstr "Служба файлової системи ресурсів Windows"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Ресурси Windows на %s"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799 ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "Цей файл не є монтованим"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "Не є звичайним файлом"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1224
+msgid "Windows Network Filesystem Service"
+msgstr "Служба мережної файлової системи Windows"
+
+#. translators: This is the name of the backend
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendtrash.c:641 ../daemon/gvfsbackendtrash.c:1229
+msgid "Trash"
+msgstr "Смітник"
+
+#: ../daemon/gvfsbackendtrash.c:1019
+#, c-format
+msgid "%s (in trash)"
+msgstr "%s (на смітнику)"
+
+#: ../daemon/gvfsbackendtrash.c:1330
+msgid "Can't delete trash"
+msgstr "Не можна видаляти смітник"
+
+#: ../daemon/gvfsbackendtrash.c:1677 ../daemon/gvfsbackendtrash.c:1752
+msgid "Trash directory notification not supported"
+msgstr "Сповіщення не підтримується для каталогу смітника"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Неправильний тип драйвера"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Помилка передачі fd: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Символічні посилання не підтримуються драйвером"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Неправильне повідомлення dbus"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Замінити старий демон."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Не запускати fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Демон GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Основна служба GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:337
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr ""
+"Для отримання додаткової інформації використовуйте команду \"%s --help\""
+
+#: ../daemon/mount.c:439
+msgid "Invalid arguments from spawned child"
+msgstr "Неправильні аргументи від дочірнього процесу"
+
+#: ../daemon/mount.c:740
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Помилка автомонтування: %s"
+
+#: ../daemon/mount.c:785
+msgid "The specified location is not mounted"
+msgstr "Вказана адреса не підключена"
+
+#: ../daemon/mount.c:790
+msgid "The specified location is not supported"
+msgstr "Вказана адреса не підтримується"
+
+#: ../daemon/mount.c:954
+msgid "Location is already mounted"
+msgstr "Адреса вже підключена"
+
+#: ../daemon/mount.c:962
+msgid "Location is not mountable"
+msgstr "Адреса не є монтованою"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Пристрій %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Пристрій %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Флопі-дисковод"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Пристрій програмного RAID"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Пристрій USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Пристрій ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Пристрій SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Пристрій FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Стрічковий накопичувач"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Пристрій CompactFlash"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Пристрій MemoryStick"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Пристрій SmartMedia"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Пристрій SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Дисковод Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Дисковод Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "USB Flash брелок"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Накопичувач"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr ""
+"Не вдається витягнути диск, оскільки один чи декілька томів цього диску "
+"зайняті."
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f КБ"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f МБ"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f ГБ"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Змішаний диск звук/дані"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Диск %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Зашифровані дані %s"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Диск CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:40 ../monitor/gphoto2/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Чистий диск CD-ROM"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Диск CD-R"
+
+#: ../monitor/hal/hal-utils.c:41 ../monitor/gphoto2/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Чистий диск CD-R"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Диск CD-RW"
+
+#: ../monitor/hal/hal-utils.c:42 ../monitor/gphoto2/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Чистий диск CD-RW"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Диск DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Чистий диск DVD-ROM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Диск DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:44 ../monitor/gphoto2/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Чистий диск DVD-RAM"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Диск DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:46 ../monitor/gphoto2/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Чистий диск DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Диск DVD+R"
+
+#: ../monitor/hal/hal-utils.c:47 ../monitor/gphoto2/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Чистий диск DVD+R"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Диск DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:48 ../monitor/gphoto2/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Чистий диск DVD+RW"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Диск DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:49 ../monitor/gphoto2/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Чистий диск DVD+R DL"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Диск Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:50 ../monitor/gphoto2/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Чистий диск Blu-Ray"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Диск Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:51 ../monitor/gphoto2/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Чистий диск Blu-Ray R"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Диск Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:52 ../monitor/gphoto2/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Чистий диск Blu-Ray RW"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Диск HD DVD"
+
+#: ../monitor/hal/hal-utils.c:53 ../monitor/gphoto2/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Чистий диск HD DVD"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Диск HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:54 ../monitor/gphoto2/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Чистий диск HD DVD-R"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Диск HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:55 ../monitor/gphoto2/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Чистий диск HD DVD-RW"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "MO Disc"
+msgstr "МО диск"
+
+#: ../monitor/hal/hal-utils.c:56 ../monitor/gphoto2/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Чистий МО диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Disc"
+msgstr "Диск"
+
+#: ../monitor/hal/hal-utils.c:57 ../monitor/gphoto2/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Чистий диск"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: помилка при відкриванні файлу: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, помилка при записі на стандартний вивід"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s, помилка при читанні: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:помилка при закритті: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "АДРЕС... - конкатенувати АДРЕСА на стандартний вивід."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"Об'єднувати всі файли у каталозі та вивести їх на стандартний вивід. Працює "
+"як стандартна утиліта cat, але замість адреси локального файлу використовує "
+"адресу gvfs. Наприклад, ви можете використовувати адресу у вигляді smb://"
+"server/resource/file.txt"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr ""
+"Примітка: якщо потрібні параметри форматування, такі як -n, -T чи інші, "
+"достатньо просто пропустити вивід через команду cat."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: не вказано адресу"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: помилка при відкритті адреси: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: помилка запуску програми: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "ФАЙЛИ... - відкриває ФАЙЛИ у зареєстрованій програмі."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr ""
+"Відкриває файл(ы) у стандартній програмі, що зареєстрована для обробки "
+"файлів цього типу."
+
+#~ msgid "File unavailable"
+#~ msgstr "Файл недоступний"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "Диск %.1f КБ"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "Диск %.1f МБ"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "Диск %.1f ГБ"
diff --git a/trunk/po/vi.po b/trunk/po/vi.po
new file mode 100644
index 00000000..5171c346
--- /dev/null
+++ b/trunk/po/vi.po
@@ -0,0 +1,1805 @@
+# Vietnamese translation for GVFS.
+# Copyright © 2009 GNOME i18n Project for Vietnamese.
+# Clytie Siddall <clytie@riverland.net.au>, 2008-2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 1.1.5\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&component=general\n"
+"POT-Creation-Date: 2009-02-04 19:03+0000\n"
+"PO-Revision-Date: 2009-02-07 17:29+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: LocFactoryEditor 1.8\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "Thao tác không được hỗ trợ, vì tập tin nằm ở điểm gắn kết khác nhau"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm lấy thông tin (get_info)"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm truy vấn thông tin (query_info)"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "Không thể lấy bộ mô tả tập tin luồng"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm mở (open)"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "Đã không lấy được bộ mô tả tập tin luồng"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm gọi (call)"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm lấy thông tin về hệ thống tập tin (get_filesystem_info)"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "Không thể tìm thấy điểm gắn kết bao bọc"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "Tên tập tin không hợp lệ %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm truy vấn thông tin về hệ thống tập tin (query_filesystem_info)"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm theo dõi thư mục (monitor_dir)"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "Giá trị đáp ứng không hợp lệ từ hàm theo dõi tập tin (monitor_file)"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081
+#: ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337
+#: ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601
+#: ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858
+#: ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944
+#: ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029
+#: ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "Thao tác bị thôi"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "Lỗi trong giao thức luồng: %s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "Kết thúc luồng"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "Chức năng seek (tìm nơi) không được hỗ trợ trên luồng"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "Thao tác truy vấn thông tin không được hỗ trợ"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "Chức năng truy vấn thông không được hỗ trợ trên luồng"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "Gặp lỗi khi lấy thông tin về điểm gắn kết: %s"
+
+#: ../client/gvfsdaemondbus.c:568
+#: ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "Gặp lỗi khi kết nối tới trình nền: %s"
+
+#: ../client/gvfsiconloadable.c:145
+#| msgid "Invalid return value from get_info"
+msgid "Invalid return value from open_icon_for_read"
+msgstr "Giá trị sai trả lại từ open_icon_for_read"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "Gặp lỗi khi tạo ổ cắm: %s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "Gặp lỗi khi kết nối tới ổ cắm: %s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "Định dạng thông tin tập tin không hợp lệ"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "Nội dung danh sách thông tin thuộc tính không hợp lệ"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+#| msgid "Error initializing camera"
+msgid "Error initializing Avahi: %s"
+msgstr "Lỗi sơ khởi Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+#| msgid "Error creating socket: %s"
+msgid "Error creating Avahi resolver: %s"
+msgstr "Lỗi tạo hàm tìm Avahi: %s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Lỗi tìm dịch vụ « %s » « %s » trên miền « %s »"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "Lỗi tìm dịch vụ « %s » « %s » trên miền « %s ». Một hay nhiều mục ghi TXT bị thiếu. Yêu cầu khoá: « %s »."
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "Quá hạn khi tìm dịch vụ « %s » « %s » trên miền « %s »"
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd encoded_triple dạng sai « %s »"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "Không thể quản lý phiên bản %d của bảng mã GVfsIcon"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "Dữ liệu nhập dạng sai cho GVfsIcon"
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "Gặp lỗi khi kết nối tới mạch nối D-Bus: %s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "Dịch vụ Hệ thống Tập tin %s"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "Lỗi: %s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "Sử dụng: %s --spawner dbus-id đường_dẫn_đối_tường"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "Sử dụng: %s khoá=giá_trị khoá=giá_trị ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "Chưa xác định kiểu điểm gắn kết"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "điểm gắn kết cho %s đã bắt đầu chạy"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "gặp lỗi khi khởi chạy trình nền gắn kết"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ trên %s"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "Chưa chỉ ra tên máy"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836
+#: ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "đặc tả gắn kết không hợp lệ"
+
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:399
+#: ../daemon/gvfsbackendftp.c:2262
+#: ../daemon/gvfsbackendnetwork.c:647
+#: ../daemon/gvfsbackendsmbbrowse.c:1085
+#: ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323
+#: ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "Tập tin không tồn tại"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:446
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:694
+msgid "The file is not a directory"
+msgstr "Tập tin không phải là một thư mục"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "Ghi chép"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "Không thể tạo thư mục tạm thời"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "Không có tập tin hay thư mục nào như vậy"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "Thư mục không rỗng"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "Không thể sao chép tập tin đè lên thư mục"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "Bộ tạo đĩa CD/DVD"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "Tập tin đã có"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "Thao tác không được hậu phương hỗ trợ"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "Không có tập tin hay thư mục nào như vậy trên đường dẫn đích đến"
+
+#: ../daemon/gvfsbackendburn.c:877
+#: ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "Không thể sao chép thư mục đè lên thư mục"
+
+#: ../daemon/gvfsbackendburn.c:886
+#: ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "Tập tin đích đã có"
+
+#: ../daemon/gvfsbackendburn.c:893
+#: ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "Không thể sao chép đệ quy thư mục"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281
+#: ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587
+#: ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "Không được hỗ trợ"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "Không thể kết nối tới mạch hệ thống"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "Không thể tạo ngữ cảnh libhal"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "Không thể khởi động libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "Chưa ghi rõ ổ đĩa"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "Không thể tìm ổ đĩa %s."
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "Ổ đĩa %s không chứa tập tin âm thanh"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "điểm gắn kết cdda trên %s"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "Đĩa âm thanh"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "Hệ thống tập tin đang bận: %d tập tin còn mở"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "Không có tập tin %s như vậy trên ồ đĩa %s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "Lỗi từ « paranoia » trên ổ đĩa %s"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "Gặp lỗi khi tìm nơi trên ổ đĩa %s"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "Không có tập tin như vậy."
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "Tập tin không tồn tại hoặc không phải là một rãnh âm thanh."
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "Dịch vụ Hệ thống Tập tin Đĩa CD Âm thanh"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "Máy tính"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "Hệ thống tập tin"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "Không thể mở thư mục"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "Không thể mở tập tin có khả năng gắn kết"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "Lỗi nội bộ : %s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "Không thể gắn kết tập tin"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "Không có vật chứa trong ổ"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "Không phải là một tập tin có khả năng gắn kết"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "Không thể tháo gắn kết tập tin"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "Không thể đẩy tập tin ra"
+
+#: ../daemon/gvfsbackenddav.c:526
+#: ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "Lỗi HTTP: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "Không thể phân tích đáp ứng"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "Đáp ứng rỗng"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "Gặp đáp ứng bất thường từ máy phục vụ"
+
+#: ../daemon/gvfsbackenddav.c:1179
+#: ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "Đáp ứng không hợp lệ"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "Vùng chia sẻ WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "Nhập mật khẩu cho %s"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "Hãy nhập mật khẩu ủy nhiệm"
+
+#: ../daemon/gvfsbackenddav.c:1662
+#: ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "Không phải một vùng chia sẻ có khả năng WebDAV"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV trên %s"
+
+#: ../daemon/gvfsbackenddav.c:1754
+#: ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "Không thể tạo yêu cầu"
+
+#: ../daemon/gvfsbackenddav.c:1890
+#: ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254
+#: ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526
+#: ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "Tập tin đích đã có"
+
+#: ../daemon/gvfsbackenddav.c:1963
+#: ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "Tập tin đã bị sửa đổi bên ngoài"
+
+#: ../daemon/gvfsbackenddav.c:1994
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "Lỗi tạo tập tin sao lưu"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:493
+#: ../daemon/gvfsbackendnetwork.c:394
+msgid "Local Network"
+msgstr "Mạng nội bộ"
+
+#: ../daemon/gvfsbackenddnssd.c:737
+#: ../daemon/gvfsbackendnetwork.c:798
+msgid "Can't monitor file or directory."
+msgstr "Không thể theo dõi tập tin hay thư mục"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:755
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:756
+#: ../daemon/gvfsbackendnetwork.c:733
+#: ../daemon/gvfsbackendnetwork.c:883
+#: ../daemon/gvfsbackendnetwork.c:884
+msgid "Network"
+msgstr "Mạng"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "Tài khoản không được hỗ trợ"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "Máy đã đóng kết nối"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "Không thể mở kết nối dữ liệu. Có thể bức tường lửa ngăn cản ?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "Kết nối dữ liệu bị đóng"
+
+#: ../daemon/gvfsbackendftp.c:271
+#: ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "Thao tác bị lỗi"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "Không có sức chứa còn rảnh trên máy phục vụ"
+
+#: ../daemon/gvfsbackendftp.c:288
+#: ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "Thao tác không được hỗ trợ"
+
+#: ../daemon/gvfsbackendftp.c:292
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "Không đủ quyền truy cập"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "Không rõ kiểu trang"
+
+#: ../daemon/gvfsbackendftp.c:300
+#: ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "Tên tập tin không hợp lệ"
+
+#: ../daemon/gvfsbackendftp.c:304
+#: ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409
+#: ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441
+#: ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "Đáp ứng không hợp lệ"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "lỗi truyền"
+
+#: ../daemon/gvfsbackendftp.c:710
+#: ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "Không thể kết nối tới máy chủ"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+#| msgid "Enter password for ftp on %s"
+msgid "Enter password for ftp as %s on %s"
+msgstr "Nhập mật khẩu cho dịch vụ FTP dưới %s trên %s"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "Nhập mật khẩu cho dịch vụ FTP trên %s"
+
+#: ../daemon/gvfsbackendftp.c:1523
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+#: ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "Hộp thoại mật khẩu bị thôi"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "FTP trên %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "FTP dưới %s trên %s"
+
+#: ../daemon/gvfsbackendftp.c:1690
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "Tập tin là thư mục"
+
+#: ../daemon/gvfsbackendftp.c:1912
+#: ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "chưa hỗ trợ chức năng sao lưu"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "tên tập tin quá dài"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "Tên tập tin đích không hợp lệt"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: Thư mục hoặc tập tin đã có"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: Không có thư mục hoặc tập tin như thế"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: Tên tập tin không hợp lệ"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: Không được hỗ trợ"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "Máy ảnh số (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823
+#: ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "Máy ảnh %s"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826
+#: ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "Bộ phát nhạc %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "Máy ảnh"
+
+#: ../daemon/gvfsbackendgphoto2.c:837
+#: ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "Bộ phát âm thanh"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "Chưa xác định thiết bị"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "Không thể tạo ngữ cảnh gphoto2"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "Lỗi tạo máy quay"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383
+#: ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "Lỗi nạp thông tin thiết bị"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "Lỗi tìm thông tin thiết bị"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "Lỗi lấy thông tin thiết bị"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "Lỗi thiết lập cổng liên lạc với máy quay"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "Lỗi khởi động máy quay"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "điểm gắn kết gphoto2 trên %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "Chưa xác định máy quay"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "Lỗi tạo đối tượng tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "Lỗi lấy tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "Lỗi lấy dữ liệu từ tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "Bộ nhận diện biểu tượng dạng sai « %s »"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772
+#: ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "Gặp lỗi dịch chuyển trong luồng của máy quay %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910
+#: ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "Không phải là một thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "Lỗi lấy danh sách thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "Lỗi lấy danh sách tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "Lỗi tạo thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "Tên đã có"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513
+#: ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "Tên mới quá dài"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "Lỗi đổi tên thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "Lỗi đổi tên tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "Thư mục '%s' không rỗng"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "Lỗi xoá thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "Lỗi xoá tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "Không thể ghi vào thư mục"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "Không thể cấp phát tập tin mới để nối thêm vào"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "Không thể đọc tập tin để nối thêm vào"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "Không thể lấy dữ liệu tập tin để nối thêm vào"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "Lỗi xoá tập tin"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "Không hỗ trợ (không cùng thư mục)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "Không hỗ trợ (nguồn thư mục, đích thư mục)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "Không hỗ trợ (nguồn thư mục, đích tập tin đã có)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "Không hỗ trợ (nguồn tập tin, đích thư mục)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "Lỗi ứng dụng khách HTTP: %s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (bảng mã không hợp lệ)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "Thông báo thư mục không được hỗ trợ"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:270
+#: ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Mạng Windows"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:932
+msgid "Network Location Monitor"
+msgstr "Theo dõi Vị trí Mạng"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s trên %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "Thiếu hỗ trợ USB. Hãy liên lạc với nhà bán phần mềm"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "Mất kết nối đến thiết bị"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "Thiết bị yêu cầu cập nhật phần mềm"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "Chương trình SSH đã thoát bất thường"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "Không rõ tên máy"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "Không có đường dẫn đến máy"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "Kết nối bị máy phục vụ từ chối"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "Lỗi thẩm tra khoá của máy"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "Không thể tạọ và thực hiện chương trình SSH"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "Không thể tạọ và thực hiện chương trình SSH: %s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "Quá hạn trong khi đăng nhập"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "Gõ cụm từ mật khẩu cho khoá"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "Gõ mật khẩu"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "Không thể gửi mật khẩu"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "Vẫn đăng nhập"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "Thôi đăng nhập"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"Không rõ máy ở xa (%s) là máy gì.\n"
+"Trường hợp này xảy ra khi bạn đăng nhập vào một máy tính lần đầu tiên.\n"
+"\n"
+"Máy tính ở xa đã gửi thông tin nhận diện là %s. Nếu bạn muốn đảm bảo là an toàn để tiếp tục, hãy liên lạc với nhà quản trị hệ thống."
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "Hộp thoại đăng nhập bị thôi"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "Không thể gửi thông tin xác nhận sự giống hệt của máy"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "Lỗi giao thức"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+#| msgid "ftp as %s on %s"
+msgid "sftp for %s on %s"
+msgstr "sftp dưới %s trên %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "SFTP trên %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "Không tìm thấy câu lệnh ssh được hỗ trợ"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "Không thành công"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721
+#: ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898
+#: ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010
+#: ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348
+#: ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512
+#: ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648
+#: ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736
+#: ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785
+#: ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "Nhận được đáp ứng không hợp lệ"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "icon_id sai '%s' trong OpenIconForRead"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "Gặp lỗi khi tạo tập tin sao lưu : %s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "Không thể tạo tập tin tạm thời"
+
+#: ../daemon/gvfsbackendsftp.c:3574
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "Không thể di chuyển thư mục đè lên thư mục"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "Yêu cầu mật khẩu cho vùng chia sẻ %s trên %s"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "Lỗi nội bộ (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "Lỗi gắn kết vùng chia sẻ Windows"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "Cách tìm nơi không được hỗ trợ"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "Gặp lỗi khi tạo tập tin sao lưu : %s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "Gặp lỗi khi xoá tập tin: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "Gặp lỗi khi di chuyển tập tin: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "Gặp lỗi khi gỡ bỏ tập tin đích: %s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "Không thể di chuyển đệ quy thư mục"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Dịch vụ Hệ thống Tập tin Chia sẻ Windows"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+#| msgid "Password required for share %s on %s"
+msgid "Password required for %s"
+msgstr "Yêu cầu mật khẩu cho %s"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Vùng chia sẻ Windows trên %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "Lỗi lấy danh sách chia sẻ từ máy phục vụ"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080
+#: ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "Tập tin không có khả năng gắn kết"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "Không phải là một tập tin tiêu chuẩn"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Dịch vụ Hệ thống Tập tin Mạng Windows"
+
+#: ../daemon/gvfsbackendtrash.c:370
+#: ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "Không cho phép xoá thư mục thùng rác"
+
+#: ../daemon/gvfsbackendtrash.c:387
+#: ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "Không cho phép sửa đổi mục vẫn còn nằm trong thùng rác"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735
+#: ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "Sọt Rác"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "Kiểu hậu phương không hợp lệ"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "Gặp lỗi khi gửi bộ mô tả tập tin: %s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "Liên kết tượng trưng không được hậu phương hỗ trợ"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "Thông điệp dbus không hợp lệ"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "Thay thế trình nền cũ."
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "Không chạy fuse."
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "Trình nền GVFS"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "Trình nền chính cho GVFS"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "Hãy thử câu lệnh trợ giúp « %s --help » để xem thông tin thêm."
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "Đối số không hợp lệ từ tiến trình con đã tạo và thực hiện"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "Lỗi tự động gắn kết: %s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "Vị trí đã ghi rõ không phải được gắn kết"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "Vị trí đã ghi rõ không được hỗ trợ"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "Vị trí đã được gắn kết"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "Vị trí không có khả năng gắn kết"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "Đĩa CD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "Đĩa CD-ROM trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "Đĩa CD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "Đĩa CD-R trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "Đĩa CD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "Đĩa CD-RW trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "Đĩa DVD-ROM"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "Đĩa DVD-ROM trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "Đĩa DVD-RAM"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "Đĩa DVD-RAM trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "Đĩa DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "Đĩa DVD-RW trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "Đĩa DVD+R"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "Đĩa DVD+R trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "Đĩa DVD+RW"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "Đĩa DVD+RW trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "Đĩa DVD+R DL"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "Đĩa DVD+R DL trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Đĩa Blu-Ray"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "Đĩa Blu-Ray trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Đĩa Blu-Ray R trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "Đĩa Blu-Ray R trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Đĩa Blu-Ray RW"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "Đĩa Blu-Ray RW trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "Đĩa HD DVD"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "Đĩa HD DVD trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "Đĩa HD DVD-R"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "Đĩa HD DVD-R trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "Đĩa HD DVD-RW"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "Đĩa HD DVD-RW trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "Đĩa MO"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "Đĩa MO trắng"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "Đĩa"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "Đĩa trắng"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "Ổ %s/%s"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "Ổ %s"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "Ổ đĩa mềm"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "Ổ phần mềm RAID"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "Ổ USB"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "Ổ đĩa ATA"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "Ổ đĩa SCSI"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "Ổ đĩa FireWire"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Ổ băng từ"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "Ổ CompactFlash (CF)"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "Ổ thanh bộ nhớ"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "Ổ vật chứa khéo"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "Ổ thẻ SD/MMC"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Ổ đĩa Zip"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Ổ đĩa Jaz"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Ổ thanh ghi nhớ"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "Ổ lưu trữ hàng loạt"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "Lỗi đẩy ra vật chứa; một hay nhiều khối tin trên vật chứa vẫn còn bận."
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "Đĩa hỗn hợp Âm thanh/Dữ liệu"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "Vật chứa %s"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "Dữ liệu mật mã %s"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: gặp lỗi khi mở tập tin: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, gặp lỗi khi ghi vào đầu ra tiêu chuẩn"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: lỗi đọc: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: lỗi đóng: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "VỊ TRÍ... — ghép nối các VỊ TRÍ ra đầu ra tiêu chuẩn."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "Ghép nối các tập tin ở vị trí, và in ra đầu ra tiêu chuẩn (stdout). Chạy đúng như tiện ích cat truyền thống, nhưng dùng vị trí gvfs thay cho tập tin cục bộ. Ví dụ, bạn có thể sử dụng cái gì như « smb://máy/tài_nguyên/tập_tin.txt » làm vị trí cần ghép nối."
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "Ghi chú : chỉ gửi dữ liệu qua ống dẫn cho tiện ích cat nếu bạn cần dùng tùy chọn định dạng của nó (v.d. « -n », « -T »)."
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: thiếu vị trí"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: gặp lỗi khi mở vị trí: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: gặp lỗi khi khởi chạy ứng dụng: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "TẬP TIN... — mở các TẬP TIN dùng ứng dụng đã đăng ký."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "Mở (các) tập tin bằng ứng dụng mặc định được đăng ký để xử lý tập tin kiểu đó."
+
diff --git a/trunk/po/zh_CN.po b/trunk/po/zh_CN.po
new file mode 100644
index 00000000..6de9e141
--- /dev/null
+++ b/trunk/po/zh_CN.po
@@ -0,0 +1,1799 @@
+# translation of gvfs.HEAD.po to Simplified Chinese
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Xin Guan <guanx.bac@gmail.com>, 2008.
+# 甘露(Gan Lu) <rhythm.gan@gmail.com>, 2009
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs.HEAD\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gvfs&amp;component=general\n"
+"POT-Creation-Date: 2008-12-12 07:42+0000\n"
+"PO-Revision-Date: 2009-01-05 20:17+0700\n"
+"Last-Translator: 甘露(Gan Lu) <rhythm.gan@gmail.com>\n"
+"Language-Team: Simplified Chinese <en@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#: ../client/gdaemonfile.c:482
+#: ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "文件在不同挂载点下,不支持此操作"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "get_info 返回无效值"
+
+#: ../client/gdaemonfile.c:816
+#: ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "query_info 返回无效值"
+
+#: ../client/gdaemonfile.c:894
+#: ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "无法取得流文件描述符"
+
+#: ../client/gdaemonfile.c:926
+#: ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055
+#: ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176
+#: ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330
+#: ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "open 返回无效值"
+
+#: ../client/gdaemonfile.c:1006
+#: ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124
+#: ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220
+#: ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "未曾取得流文件描述符"
+
+#: ../client/gdaemonfile.c:1238
+#: ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "返回值无效"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "get_filesystem_info 返回无效值"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "找不到所属挂载点"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "无效文件名:%s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "query_filesystem_info 返回无效值"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "monitor_dir 返回无效值"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "monitor_file 返回无效值"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831
+#: ../daemon/gvfsbackendobexftp.c:741
+#: ../daemon/gvfsbackendobexftp.c:762
+#: ../daemon/gvfsbackendobexftp.c:881
+#: ../daemon/gvfsbackendobexftp.c:1018
+#: ../daemon/gvfsbackendobexftp.c:1082
+#: ../daemon/gvfsbackendobexftp.c:1219
+#: ../daemon/gvfsbackendobexftp.c:1246
+#: ../daemon/gvfsbackendobexftp.c:1305
+#: ../daemon/gvfsbackendobexftp.c:1327
+#: ../daemon/gvfsbackendobexftp.c:1387
+#: ../daemon/gvfsbackendobexftp.c:1406
+#: ../daemon/gvfsbackendsmb.c:1105
+#: ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120
+#: ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+msgid "Operation was cancelled"
+msgstr "操作被取消"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "流协议 %s 有错"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "流终止"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "流不支持搜索"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "不支持“query info”操作"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "不支持在流媒体上查询信息"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "获取挂载信息时出错:%s"
+
+#: ../client/gvfsdaemondbus.c:568
+#: ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "连接守护进程出错:%s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "返回无效值"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "建立套接字出错:%s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "连接套接字出错:%s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "无效的文件信息格式:%s"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "属性信息列表内容无效"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "初始化 Avahi 时出错:%s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "创建 Avahi 解析器时出错:%s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析 \"%1$s\" 在域 \"%3$s\" 上的 \"%2$s\" 服务时出错"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT records are missing. Keys required: \"%s\"."
+msgstr "解析 \"%1$s\" 在域 \"%3$s\" 上的 \"%2$s\" 服务时出错。一个或多个 TXT 记录丢失。要求密匙:\"%4$s\""
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析 \"%1$s\" 在域 \"%3$s\" 上的 \"%2$s\" 服务时超时"
+
+#: ../common/gvfsdnssdutils.c:233
+#: ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr "dns-sd encoded_triple '%s' 格式错误"
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "无法处理 GVfsIcon 编码版本 %d"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon的输入数据格式错误"
+
+#: ../daemon/daemon-main.c:63
+#: ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "连接 D-Bus 出错:%s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s 文件系统服务"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "错误:%s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "用法:%s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155
+#: ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "用法:%s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "未指定挂载类型"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s 的挂载点已在运行"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "启动挂载守护进程失败"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315
+#: ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "%s 上的 /"
+
+#: ../daemon/gvfsbackendarchive.c:515
+#: ../daemon/gvfsbackendftp.c:1632
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "未指定主机名"
+
+#: ../daemon/gvfsbackendarchive.c:526
+#: ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591
+#: ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:561
+#: ../daemon/gvfsbackendobexftp.c:572
+#: ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "无效的挂载描述"
+
+#: ../daemon/gvfsbackendarchive.c:636
+#: ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715
+#: ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572
+#: ../daemon/gvfsbackenddnssd.c:393
+#: ../daemon/gvfsbackendftp.c:2254
+#: ../daemon/gvfsbackendnetwork.c:590
+#: ../daemon/gvfsbackendsmbbrowse.c:804
+#: ../daemon/gvfsbackendsmbbrowse.c:871
+#: ../daemon/gvfsbackendsmbbrowse.c:1042
+#: ../daemon/gvfsbackendsmbbrowse.c:1111
+#, c-format
+msgid "File doesn't exist"
+msgstr "文件不存在"
+
+#: ../daemon/gvfsbackendarchive.c:724
+#: ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651
+#: ../daemon/gvfsbackenddnssd.c:440
+#: ../daemon/gvfsbackendftp.c:1043
+#: ../daemon/gvfsbackendnetwork.c:637
+msgid "The file is not a directory"
+msgstr "此文件不是目录文件"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "烧录"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "无法创建临时目录"
+
+#: ../daemon/gvfsbackendburn.c:405
+#: ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451
+#: ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719
+#: ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783
+#: ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916
+#: ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:211
+#, c-format
+msgid "No such file or directory"
+msgstr "文件或目录不存在"
+
+#: ../daemon/gvfsbackendburn.c:425
+#: ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "目录非空"
+
+#: ../daemon/gvfsbackendburn.c:459
+#: ../daemon/gvfsbackendburn.c:906
+msgid "Can't copy file over directory"
+msgstr "不能将文件复制到目录上"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD 生成器"
+
+#: ../daemon/gvfsbackendburn.c:755
+#: ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926
+#: ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "文件已存在"
+
+#: ../daemon/gvfsbackendburn.c:829
+#: ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120
+#: ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140
+#: ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174
+#: ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122
+#: ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122
+#: ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156
+#: ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130
+#: ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162
+#: ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120
+#: ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173
+#: ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131
+#: ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120
+#: ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119
+#: ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127
+#: ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146
+#: ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "后端不支持此操作"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "目的路径中不存在此文件或目录"
+
+#: ../daemon/gvfsbackendburn.c:877
+msgid "Can't copy directory over directory"
+msgstr "不能将目录复制到目录上"
+
+#: ../daemon/gvfsbackendburn.c:886
+msgid "Target file exists"
+msgstr "目标文件已存在"
+
+#: ../daemon/gvfsbackendburn.c:893
+msgid "Can't recursively copy directory"
+msgstr "无法递归复制目录"
+
+#: ../daemon/gvfsbackendburn.c:952
+#: ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281
+#: ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587
+#: ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "不支持"
+
+#: ../daemon/gvfsbackendcdda.c:299
+#: ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "无法连接到系统主线"
+
+#: ../daemon/gvfsbackendcdda.c:310
+#: ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "无法创建 libhal 上下文"
+
+#: ../daemon/gvfsbackendcdda.c:324
+#: ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "无法初始化 libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339
+#: ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "未指定驱动器"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "找不到驱动器 %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "驱动器 %s 不含音频文件"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "%s 上挂载的 cdda"
+
+#: ../daemon/gvfsbackendcdda.c:378
+#: ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435
+#: ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "音频光盘"
+
+#: ../daemon/gvfsbackendcdda.c:439
+#: ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "文件系统忙:打开了 %d 个文件"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "文件 %s 在驱动器 %s 上不存在"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "驱动器 %s 上有错误来自 'paranoia'"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "在驱动器 %s 上的流搜索时出错"
+
+#: ../daemon/gvfsbackendcdda.c:914
+#: ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "无此文件"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "文件不存在或不是音轨"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "音频 CD 文件系统服务"
+
+#: ../daemon/gvfsbackendcomputer.c:179
+#: ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "计算机"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "文件系统"
+
+#: ../daemon/gvfsbackendcomputer.c:590
+#: ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:727
+#: ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:227
+#, c-format
+msgid "Can't open directory"
+msgstr "无法打开目录"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "无法打开可挂载文件"
+
+#: ../daemon/gvfsbackendcomputer.c:779
+#: ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "内部错误:%s"
+
+#: ../daemon/gvfsbackendcomputer.c:811
+#: ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "无法挂载文件"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "驱动器中没有介质"
+
+#: ../daemon/gvfsbackendcomputer.c:880
+#: ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "非可挂载文件"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "无法卸载文件"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "无法弹出文件"
+
+#: ../daemon/gvfsbackenddav.c:526
+#: ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP 错误:%s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "无法分析响应"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "空响应"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "服务器给出意外回复"
+
+#: ../daemon/gvfsbackenddav.c:1179
+#: ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "响应无效"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV 共享"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "输入 %s 的密码"
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "请输入代理密码"
+
+#: ../daemon/gvfsbackenddav.c:1662
+#: ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "不是 WebDAV 使能的共享"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "%s 上的 WebDAV 共享"
+
+#: ../daemon/gvfsbackenddav.c:1754
+#: ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "无法创建请求"
+
+#: ../daemon/gvfsbackenddav.c:1890
+#: ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254
+#: ../daemon/gvfsbackendftp.c:1852
+#: ../daemon/gvfsbackendftp.c:2518
+#: ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "目标文件已存在"
+
+#: ../daemon/gvfsbackenddav.c:1963
+#: ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "文件被其它程序更改"
+
+#: ../daemon/gvfsbackenddav.c:1994
+#: ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "建立备份文件失败"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:487
+#: ../daemon/gvfsbackendnetwork.c:392
+msgid "Local Network"
+msgstr "本地网络"
+
+#: ../daemon/gvfsbackenddnssd.c:731
+#: ../daemon/gvfsbackendnetwork.c:731
+msgid "Can't monitor file or directory."
+msgstr "无法监视文件或目录"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:749
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:750
+#: ../daemon/gvfsbackendnetwork.c:676
+#: ../daemon/gvfsbackendnetwork.c:814
+#: ../daemon/gvfsbackendnetwork.c:815
+msgid "Network"
+msgstr "网络"
+
+#: ../daemon/gvfsbackendftp.c:251
+msgid "Accounts are unsupported"
+msgstr "不支持这些帐号"
+
+#: ../daemon/gvfsbackendftp.c:255
+msgid "Host closed connection"
+msgstr "主机已关闭连接"
+
+#: ../daemon/gvfsbackendftp.c:259
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "无法打开数据连接。是不是您的防火墙不允许?"
+
+#: ../daemon/gvfsbackendftp.c:263
+msgid "Data connection closed"
+msgstr "数据连接已关闭"
+
+#: ../daemon/gvfsbackendftp.c:270
+#: ../daemon/gvfsbackendftp.c:274
+msgid "Operation failed"
+msgstr "操作失败"
+
+#: ../daemon/gvfsbackendftp.c:279
+msgid "No space left on server"
+msgstr "服务器上没有剩余空间了"
+
+#: ../daemon/gvfsbackendftp.c:287
+#: ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "不支持此操作"
+
+#: ../daemon/gvfsbackendftp.c:291
+#: ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "权限不足"
+
+#: ../daemon/gvfsbackendftp.c:295
+msgid "Page type unknown"
+msgstr "页面类型未知"
+
+#: ../daemon/gvfsbackendftp.c:299
+#: ../daemon/gvfsbackendftp.c:2364
+msgid "Invalid filename"
+msgstr "无效文件名"
+
+#: ../daemon/gvfsbackendftp.c:303
+#: ../daemon/gvfsbackendftp.c:379
+#: ../daemon/gvfsbackendftp.c:408
+#: ../daemon/gvfsbackendftp.c:427
+#: ../daemon/gvfsbackendftp.c:440
+#: ../daemon/gvfsbackendftp.c:928
+msgid "Invalid reply"
+msgstr "无效回复"
+
+#: ../daemon/gvfsbackendftp.c:547
+msgid "broken transmission"
+msgstr "传输损坏"
+
+#: ../daemon/gvfsbackendftp.c:709
+#: ../daemon/gvfsbackendftp.c:850
+msgid "Could not connect to host"
+msgstr "无法连接到主机"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1486
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "请输入 %2$s 上 %1$s 的 ftp 密码"
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1489
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "请输入 %s 上 ftp 的密码"
+
+#: ../daemon/gvfsbackendftp.c:1515
+#: ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599
+msgid "Password dialog cancelled"
+msgstr "密码对话框被取消"
+
+#: ../daemon/gvfsbackendftp.c:1594
+#, c-format
+msgid "ftp on %s"
+msgstr "%s 上的 ftp"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1598
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "以 %s ftp 到 %s"
+
+#: ../daemon/gvfsbackendftp.c:1682
+#: ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "此文件是目录文件"
+
+#: ../daemon/gvfsbackendftp.c:1904
+#: ../daemon/gvfsbackendftp.c:2479
+msgid "backups not supported yet"
+msgstr "尚不支持备份"
+
+#: ../daemon/gvfsbackendftp.c:1981
+msgid "filename too long"
+msgstr "文件名过长"
+
+#: ../daemon/gvfsbackendftp.c:2498
+msgid "Invalid destination filename"
+msgstr "无效目标文件名"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s: %d: 目录或文件已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s: %d: 没有该文件或目录"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s: %d: 无效的文件名"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s: %d: 不支持"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "数码相机(%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823
+#: ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s 相机"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826
+#: ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s 音频播放器"
+
+#: ../daemon/gvfsbackendgphoto2.c:835
+#: ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "相机"
+
+#: ../daemon/gvfsbackendgphoto2.c:837
+#: ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "音频播放器"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "未指定设备"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "无法创建 gphoto2 上下文"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "创建照相机时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383
+#: ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "载入设备信息时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "查找设备信息时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "获取设备信息时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "设置照相机通信端口时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "初始化照相机时出错"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "%s 上的 gphoto2 挂载"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "未指定照相机"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "创建文件对象时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "获取文件时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "从文件中获取数据时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "图标识别符 '%s' 的格式错误"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772
+#: ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "在照相机 %s 上的流搜索时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910
+#: ../daemon/gvfsbackendsmbbrowse.c:1107
+msgid "Not a directory"
+msgstr "不是目录"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "无法得到文件夹列表"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "无法得到文件列表"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "创建目录时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "名字已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513
+#: ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "新名字过长"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523
+#: ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "重命名目录时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536
+#: ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "重命名文件时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "目录 '%s' 非空"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "删除目录时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "删除文件时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "无法写入目录"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "无法分配新文件以增补到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "无法读取文件以增补到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "无法得到文件数据以增补到"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "写入文件时出错"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "不支持(不是同一目录)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "不支持(源为目录,目标地也为目录)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "不支持(源为目录,目标地为已存文件)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "不支持(源为文件,目标地为目录)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP 客户端错误:%s"
+
+#: ../daemon/gvfsbackendhttp.c:570
+#: ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337
+#: ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr " (无效编码)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "不支持目录通知"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:268
+#: ../daemon/gvfsbackendsmbbrowse.c:699
+msgid "Windows Network"
+msgstr "Windows 网络"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:862
+msgid "Network Location Monitor"
+msgstr "网络位置监测器"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:387
+#: ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%2$s 上的 %1$s"
+
+#: ../daemon/gvfsbackendobexftp.c:666
+msgid "Connection to the device lost"
+msgstr "丢失与设备的连接"
+
+#: ../daemon/gvfsbackendobexftp.c:1163
+msgid "Device requires a software update"
+msgstr "设备要求一个软件更新"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh 程序意外退出"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "主机名未知"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "没有到主机的路由"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "服务器拒绝连接"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "主机密钥认证失败"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "无法调用 ssh 程序"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "无法调用 ssh 程序:%s"
+
+#: ../daemon/gvfsbackendsftp.c:535
+#: ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "登录超时"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "输入此密钥的口令"
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "输入密码"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "无法发送密码"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "仍登入"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "取消登录"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely sure it is safe to continue, contact the system administrator."
+msgstr ""
+"远程计算机(%s)的身份未知。\n"
+"这发生在您首次登录此计算机时。\n"
+"\n"
+"远程计算机发送的身份是 %s。如果您想确认继续操作是安全的,请联系其系统管理员。"
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "登录对话框被取消"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "无法发送主机身份确认信息"
+
+#: ../daemon/gvfsbackendsftp.c:1479
+#: ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "协议错误"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "在 %2$s 上的 %1$s sftp"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "%s 上的 sftp"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "无法找到支持的 ssh 命令"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "失败"
+
+#: ../daemon/gvfsbackendsftp.c:2032
+#: ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122
+#: ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264
+#: ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360
+#: ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542
+#: ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632
+#: ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721
+#: ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898
+#: ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010
+#: ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348
+#: ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512
+#: ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648
+#: ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736
+#: ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785
+#: ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "收到无效回复"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead 中无效的 icon_id '%s' "
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "创建备份文件出错:%s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "无法创建临时文件"
+
+#: ../daemon/gvfsbackendsftp.c:3574
+#: ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "不能将目录移动到目录上"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "共享 %s 于 %s 需要密码"
+
+#: ../daemon/gvfsbackendsmb.c:478
+#: ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "内部错误(%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "挂载 Windows 共享失败"
+
+#: ../daemon/gvfsbackendsmb.c:753
+#: ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "不支持此搜索类型"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "创建备份文件失败:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "删除文件失败:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "移动文件失败:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "删除目标文件失败:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "无法递归删除目录"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows 共享文件系统服务"
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:707
+#, c-format
+msgid "Windows shares on %s"
+msgstr "%s 上的 Windows 共享"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:799
+#: ../daemon/gvfsbackendsmbbrowse.c:845
+msgid "The file is not a mountable"
+msgstr "此文件不可挂载"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:867
+msgid "Not a regular file"
+msgstr "非常规文件"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1219
+msgid "Windows Network Filesystem Service"
+msgstr "Windows 网络文件系统服务"
+
+#: ../daemon/gvfsbackendtrash.c:334
+#, c-format
+msgid "Can't delete trash"
+msgstr "不能删除垃圾"
+
+#: ../daemon/gvfsbackendtrash.c:348
+#: ../daemon/gvfsbackendtrash.c:399
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "垃圾箱中的项目也许不能修改"
+
+#: ../daemon/gvfsbackendtrash.c:385
+#, c-format
+msgid "Can't pull trash"
+msgstr "无法清空垃圾箱"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:650
+#: ../daemon/gvfsbackendtrash.c:758
+msgid "Trash"
+msgstr "垃圾箱"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "无效后端类型"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "发送文件描述符出错:%s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "后端不支持符号链接"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "无效的 dbus 消息"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "替换旧守护进程。"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "请勿起动 fuse"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS 守护进程"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GVFS 主守护进程"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s:%s"
+
+#: ../daemon/main.c:78
+#: ../programs/gvfs-cat.c:163
+#: ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101
+#: ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386
+#: ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97
+#: ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144
+#: ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "请用 \"%s --help\" 获得更多信息。"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "来自所调用子进程的参数无效"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "自动挂载失败:%s"
+
+#: ../daemon/mount.c:812
+#: ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "指定未知未挂载"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "不支持指定未知"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "位置已挂载"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "位置不可挂载"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:40
+#: ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "空白 CD-ROM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:41
+#: ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "空白 CD-R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:42
+#: ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "空白 CD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:43
+#: ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43
+#: ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "空白 DVD-ROM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:44
+#: ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "空白 DVD-RAM 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:46
+#: ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "空白 DVD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:47
+#: ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "空白 DVD+R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:48
+#: ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "空白 DVD+RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:49
+#: ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "空白 DVD+R DL 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:50
+#: ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "空白 Blu-Ray 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:51
+#: ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "空白 Blu-Ray R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:52
+#: ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "空白 Blu-Ray RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:53
+#: ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "空白 HD DVD 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:54
+#: ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "空白 HD DVD-R 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:55
+#: ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "空白 HD DVD-RW 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:56
+#: ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "空白 MO 盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "盘片"
+
+#: ../monitor/gphoto2/hal-utils.c:57
+#: ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "空白盘片"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s 驱动器"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "软盘驱动器"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "软件 RAID 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "Tape 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "Thumb 驱动器"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "大容量存储驱动器"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "弹出介质失败:介质上的一个或多个卷正忙"
+
+#: ../monitor/hal/ghalmount.c:301
+#: ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306
+#: ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311
+#: ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433
+#: ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "音频/数据混合盘"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446
+#: ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s 介质"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s 加密数据"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s: 打开文件出错: %s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s, 写 stdout 出错"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s: 读取出错: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s: 关闭出错: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "位置... - 将“位置”续接到标准输出."
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid "Concatenate files at locations and print to the standard output. Works just like the traditional cat utility, but using gvfs location instead local files: for example you can use something like smb://server/resource/file.txt as location to concatenate."
+msgstr "续接“位置”处的文件到标准输出来打印其内容。与传统的 cat 程序类似,但使用 gvfs 位置而不是本地文件。例如:可以用 smb://server/resource/file.txt 作为位置来续接。"
+
+#: ../programs/gvfs-cat.c:148
+msgid "Note: just pipe through cat if you need its formatting option like -n, -T or other."
+msgstr "注意:如需要 cat 的 -n, -T 之类格式化功能,可通过管道用 cat 过滤。"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174
+#: ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s: 位置缺失"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s: 打开位置出错: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s: 启动应用出错: %s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - 用注册的应用打开 FILES。"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid "Opens the file(s) with the default application registered to handle the type of the file."
+msgstr "使用注册的用于处理此类文件的应用打开此文件。"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+#~ msgid "File unavailable"
+#~ msgstr "文件不可用"
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (垃圾箱中)"
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "不支持垃圾目录 notificatioin"
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB 介质"
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB 介质"
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB 介质"
+#~ msgid "Invalid reply from server"
+#~ msgstr "服务器回复无效"
+#~ msgid "File does not exist"
+#~ msgstr "文件不存在"
+
diff --git a/trunk/po/zh_HK.po b/trunk/po/zh_HK.po
new file mode 100644
index 00000000..7e4a98ec
--- /dev/null
+++ b/trunk/po/zh_HK.po
@@ -0,0 +1,1652 @@
+# Chinese (Hong Kong) translation of gvfs.
+# Copyright (C) 2003-06 Free Software Foundation, Inc.
+# Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>, 2008
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 1.1.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-09 07:54+0800\n"
+"PO-Revision-Date: 2009-02-09 07:54+0800\n"
+"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
+"Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "檔案在不同掛載點,不支援此操作"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "從 get_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "從 query_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "無法取得串流檔案檔案描述器"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "從開啟中傳回無效的數值"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "不要取得串流檔案檔案描述器"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "從呼叫中傳回無效的數值"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "從 get_filesystem_info 傳回無效的數值"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "找不到所屬掛載點"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "無效的檔案名稱 %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "從 query_filesystem_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "從 monitor_dir 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "從 monitor_file 傳回無效的數值"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "操作已被取消"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "串流通訊協定發生錯誤:%s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "串流結尾"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "不支援在串流中搜尋"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "不支援此查詢資訊的操作"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "串流不支援查詢資訊"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "取得掛載資訊時發生錯誤:%s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "連線到伺服程式發生錯誤:%s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "從 open_icon_for_read 傳回無效的數值"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "建立 socket 時發生錯誤:%s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "連線至 socket 時發生錯誤:%s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "無效的檔案資訊格式"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "無效的屬性資訊清單內容"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "初始化 Avahi 時發生錯誤:%s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "建立 Avahi 解析器時發生錯誤:%s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析網域「%3$s」上服務「%2$s」的「%1$s」時發生錯誤"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr "解析網域「%3$s」上服務「%2$s」的「%1$s」時發生錯誤。一或多個 TXT 紀錄遺失。需要設定鍵:「%4$s」"
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析網域「%3$s」上服務「%2$s」的「%1$s」逾時"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr ""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "不能處理 GVfsIcon 編碼的版本 %d"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon 的輸入資料格式不良"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "連線到 D-Bus 時發生錯誤:%s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s 檔案系統服務"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "錯誤:%s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "用法:%s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "用法: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "未指定掛載類型"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s 的掛載點已在使用中"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "啟動掛載伺服程式的發生錯誤"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ 於 %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "未指定主機名稱"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "無效的掛載資料"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "檔案不存在"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "該檔案不是目錄"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "燒錄"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "無法建立暫存目錄"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "目錄不是空的"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "不能將檔案複製到目錄上"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD 製作程式"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "檔案已存在"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "後端不支援此操作"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "在目標路徑沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "不能將目錄複製到目錄上"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "目標檔案已存在"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "不能遞廻複製目錄"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "不支援"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "不能連線到系統匯流排"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "不能建立 libhal 脈絡"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "不能初始化 libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "未指定裝置"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "找不到到裝置 %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "裝置 %s 中不包含音樂檔案"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda 掛載於 %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "音樂光碟"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "檔案系統忙碌中:開啟了 %d 個檔案"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "磁碟 %2$s 中沒有檔案 %1$s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "來自磁碟 %s 上的「paranoia」的錯誤"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "在磁碟 %s 上搜尋串流發生錯誤"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "沒有這個檔案"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "檔案不存在或不是音軌"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "音樂 CD 檔案系統服務"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "電腦"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "檔案系統"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "不能開啟目錄"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "不能開啟可掛載式檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "內部的錯誤:%s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "不能掛載檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "裝置中沒有媒體"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "不是可掛載式檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "不能卸載檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "不能退出檔案"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP 錯誤: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "無法解析回應"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "空白的回應"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "來自伺服器未預期的回應"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "回應無效"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV 分享"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "輸入 %s 的密碼 "
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "請輸入代理伺服器密碼"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "不是使用 WebDAV 的分享"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV 於 %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "無法建立要求"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "目標檔案已存在"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "該檔案已被外部程式修改過"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "建立備份檔案失敗"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "本地端網絡"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "不能監控檔案或目錄。"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "網絡"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "帳號不被支援"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "主機關閉連線"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "無法開啟資料連線。也許你的防火牆阻擋了它?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "資料連線已關閉"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "操作已失敗"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "伺服器中沒有剩餘空間"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "操作不被支援"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "權限不足"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "頁面類型不明"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "無效的檔案名稱"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "無效的回應"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "損壞的傳輸"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "無法連線至主機"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "輸入 %s 在 %s 上的 ftp 密碼 "
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "輸入 %s 的 ftp 密碼 "
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "密碼對話盒已被取消"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp 於 %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "以 %s 登入 %s 的 ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "檔案是目錄"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "備份尚未支援"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "檔案名稱太長"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "無效的目的端檔案名稱"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s:%d:目錄或檔案已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s:%d:沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s:%d:無效的檔案名稱"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s:%d:不支援"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "數碼相機 (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s 照相機"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s 音樂播放機"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "照相機"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "音樂播放機"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "未指定裝置"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "不能建立 gphoto2 脈絡"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "建立攝影機發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "載入裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "尋找裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "取得裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "設定攝影機通訊埠時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "初始化攝影機發生錯誤"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 掛載於 %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "未指定攝影機"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "建立檔案物件發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "讀取檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "從檔案取得資料時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "圖示識別符「%s」格式不良"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "在攝影機 %s 上搜尋串流發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "不是一個目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "取得資料夾清單失敗"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "取得檔案清單失敗"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "建立目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "名稱已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "新的名稱太長"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "重新命名目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "重新命名檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "目錄「%s」不是空的"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "刪除目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "刪除檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "不能寫入至目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "不能分配新檔案加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "不能讀取檔案加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "不能取得檔案的資料加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "寫入檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "不支援(不同目錄)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "不支援(來源是目錄,目的也是目錄)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "不支援(來源是目錄,目的是既存的檔案)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "不支援(來源是檔案,目的是目錄)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP 客戶端錯誤:%s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr "(無效的編碼)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "不支援目錄通知"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows 網絡"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "網絡位置監視器"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s 於 %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB 支援遺失。請聯絡你的軟件廠商"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "到裝置的連線已失去"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "裝置要求更新軟件"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh 程式意外的中止了"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "主機名稱不明"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "沒有路由可到主機"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "連線被伺服器拒絕"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "驗證主機密碼匙失敗"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "無法呼叫 ssh 程式"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "無法呼叫 ssh 程式:%s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "登入逾時時間"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "輸入密碼匙的密語 "
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "輸入密碼"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "不能傳送密碼"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "強制登入"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "取消登入"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"遠端電腦 (%s) 的識別不明。\n"
+"這通常發生在你第一次登入電腦的時候。\n"
+"\n"
+"由遠端電腦傳送的識別為 %s。如果你想要完全確定繼續是安全的,請聯絡系統管理者。"
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "登入對話盒已被取消"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "不能傳送主機識別確認"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "通訊協定錯誤"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp 以 %s 於 %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp 於 %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "找不到支援的 ssh 指令"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "失敗"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "收到無效的回應"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead 中有無效的 icon_id 「%s」"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "建立備份檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "無法建立暫存檔案"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "不能將目錄移動至目錄上"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "要分享 %2$s 上的 %1$s 需要密碼"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "內部的錯誤 (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "掛載 Windows 分享失敗"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "不支援的搜尋類型"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "建立備份檔案失敗:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "刪除檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "移動檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "移除目標檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "不能循環移動目錄"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows 分享檔案系統服務"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s 需要的密碼 "
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows 分享於 %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "從伺服器取回分享清單失敗"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "該檔案是無法掛載的"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "不是正規的檔案"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows 網絡檔案系統服務"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "回收筒資料來不能刪除"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "回收筒中的項目不能修改"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "回收筒"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "無效的後端類型"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "傳送 fd 時發生錯誤:%s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "後端不支援符號連結"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "無效的 dbus 訊息"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "置換舊的伺服程式。"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "不啟動 fuse。"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS 伺服程式"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GCFS 主伺服程式"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "使用「%s --help」以獲得更多資訊。"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "來自衍生子程序的無效引數"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "自動掛載失敗:%s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "指定的位置尚未掛載"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "指定的位置不被支援"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "該位置已經掛載了"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "該位置不是可掛載的"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "空白 CD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "空白 CD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "空白 CD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "空白 DVD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "空白 DVD-RAM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "空白 DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "空白 DVD+R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "空白 DVD+RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "空白 DVD+R DL 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "空白 Blu-Ray 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "空白 Blu-Ray R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "空白 Blu-Ray RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "空白 HD DVD 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "空白 HD DVD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "空白 HD DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "空白 MO 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "空白光碟"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s 光碟機"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s 光碟機"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "軟碟機"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "軟件 RAID 陣列"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI 裝置"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "磁帶機"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash 裝置"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick 裝置"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia 裝置"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC 裝置"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "隨身碟"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "大量存放裝置"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "退出媒體失敗;該媒體上的一或多個儲存裝置正在忙碌。"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "混合音樂/資料光碟"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s 媒體"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s 加密的資料"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s:開啟檔案時發生錯誤:%s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s,錯誤寫入至 stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s:讀取檔案時發生錯誤:%s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:發生錯誤時正關閉: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - 將 LOCATIONS 連接至標準輸出。"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr "連接位置上的檔案並顯示到標準輸出。運作方式就像傳統的 cat 公用程式,只是使用 gvfs 位置代替 local 檔案:例如你可以使用像 smb://server/resource/file.txt 做為連接的位置。"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "注意:只要利用導管通過 cat 就可以使用它的格式選項如 -n, -T 或其他。"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s:漏掉位置"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s:發生錯誤時正開啟位置: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s:執行應用程式時發生錯誤:%s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - 以註冊的應用程式開啟 FILES。"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "使用註冊為處理該檔案類型的預設應用程式來開啟檔案。"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (於回收筒)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "無法刪除回收筒"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "不支援目錄通知"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "建立通訊埠資訊清單時發生錯誤"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "從通訊埠資訊清單取得通訊埠資訊時發生錯誤"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "檔案系統忙碌中:開啟了 %d 個檔案"
+
+#~ msgid "Error listing folders"
+#~ msgstr "列出資料夾時發生錯誤"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "列出資料夾中的檔案時發生錯誤"
+
+#~ msgid "File unavailable"
+#~ msgstr "檔案無法使用"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB 媒體"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB 媒體"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB 媒體"
diff --git a/trunk/po/zh_TW.po b/trunk/po/zh_TW.po
new file mode 100644
index 00000000..cae6bc90
--- /dev/null
+++ b/trunk/po/zh_TW.po
@@ -0,0 +1,1657 @@
+# Chinese (Taiwan) translation of gvfs.
+# Copyright (C) 2003-06 Free Software Foundation, Inc.
+# Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>, 2008
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gvfs 1.1.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-02-09 07:54+0800\n"
+"PO-Revision-Date: 2009-02-08 19:31+0800\n"
+"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
+"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../client/gdaemonfile.c:482 ../client/gdaemonfile.c:1984
+msgid "Operation not supported, files on different mounts"
+msgstr "檔案在不同掛載點,不支援此操作"
+
+#: ../client/gdaemonfile.c:787
+msgid "Invalid return value from get_info"
+msgstr "從 get_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:816 ../client/gdaemonfile.c:1563
+msgid "Invalid return value from query_info"
+msgstr "從 query_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:894 ../client/gvfsiconloadable.c:338
+msgid "Couldn't get stream file descriptor"
+msgstr "無法取得串流檔案檔案描述器"
+
+#: ../client/gdaemonfile.c:926 ../client/gdaemonfile.c:996
+#: ../client/gdaemonfile.c:1055 ../client/gdaemonfile.c:1114
+#: ../client/gdaemonfile.c:1176 ../client/gdaemonfile.c:2252
+#: ../client/gdaemonfile.c:2330 ../client/gdaemonfile.c:2589
+#: ../client/gvfsiconloadable.c:370
+msgid "Invalid return value from open"
+msgstr "從開啟中傳回無效的數值"
+
+#: ../client/gdaemonfile.c:1006 ../client/gdaemonfile.c:1065
+#: ../client/gdaemonfile.c:1124 ../client/gdaemonfile.c:1186
+#: ../client/gdaemonfile.c:2220 ../client/gvfsiconloadable.c:155
+msgid "Didn't get stream file descriptor"
+msgstr "不要取得串流檔案檔案描述器"
+
+#: ../client/gdaemonfile.c:1238 ../client/gdaemonfile.c:1255
+msgid "Invalid return value from call"
+msgstr "從呼叫中傳回無效的數值"
+
+#: ../client/gdaemonfile.c:1534
+msgid "Invalid return value from get_filesystem_info"
+msgstr "從 get_filesystem_info 傳回無效的數值"
+
+#. translators: this is an error message when there is no user visible "mount" object
+#. corresponding to a particular path/uri
+#: ../client/gdaemonfile.c:1647
+msgid "Could not find enclosing mount"
+msgstr "找不到所屬掛載點"
+
+#: ../client/gdaemonfile.c:1677
+#, c-format
+msgid "Invalid filename %s"
+msgstr "無效的檔案名稱 %s"
+
+#: ../client/gdaemonfile.c:1719
+msgid "Invalid return value from query_filesystem_info"
+msgstr "從 query_filesystem_info 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:2142
+msgid "Invalid return value from monitor_dir"
+msgstr "從 monitor_dir 傳回無效的數值"
+
+#: ../client/gdaemonfile.c:2191
+msgid "Invalid return value from monitor_file"
+msgstr "從 monitor_file 傳回無效的數值"
+
+#: ../client/gdaemonfileenumerator.c:351
+#: ../client/gdaemonfileinputstream.c:518
+#: ../client/gdaemonfileinputstream.c:674
+#: ../client/gdaemonfileinputstream.c:782
+#: ../client/gdaemonfileinputstream.c:1032
+#: ../client/gdaemonfileoutputstream.c:458
+#: ../client/gdaemonfileoutputstream.c:636
+#: ../client/gdaemonfileoutputstream.c:831 ../daemon/gvfsbackendobexftp.c:1060
+#: ../daemon/gvfsbackendobexftp.c:1081 ../daemon/gvfsbackendobexftp.c:1200
+#: ../daemon/gvfsbackendobexftp.c:1337 ../daemon/gvfsbackendobexftp.c:1401
+#: ../daemon/gvfsbackendobexftp.c:1601 ../daemon/gvfsbackendobexftp.c:1708
+#: ../daemon/gvfsbackendobexftp.c:1858 ../daemon/gvfsbackendobexftp.c:1885
+#: ../daemon/gvfsbackendobexftp.c:1944 ../daemon/gvfsbackendobexftp.c:1966
+#: ../daemon/gvfsbackendobexftp.c:2029 ../daemon/gvfsbackendobexftp.c:2048
+#: ../daemon/gvfsbackendsmb.c:1105 ../daemon/gvfsbackendtest.c:87
+#: ../daemon/gvfsbackendtest.c:120 ../daemon/gvfsbackendtest.c:183
+#: ../daemon/gvfschannel.c:298
+#, c-format
+msgid "Operation was cancelled"
+msgstr "操作已被取消"
+
+#: ../client/gdaemonfileinputstream.c:450
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1300
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:402
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1054
+#: ../client/gdaemonfileoutputstream.c:1064
+#, c-format
+msgid "Error in stream protocol: %s"
+msgstr "串流通訊協定發生錯誤:%s"
+
+#: ../client/gdaemonfileinputstream.c:458
+#: ../client/gdaemonfileinputstream.c:1310
+#: ../client/gdaemonfileoutputstream.c:410
+#: ../client/gdaemonfileoutputstream.c:1064
+msgid "End of stream"
+msgstr "串流結尾"
+
+#: ../client/gdaemonfileinputstream.c:1207
+#: ../client/gdaemonfileoutputstream.c:942
+msgid "Seek not supported on stream"
+msgstr "不支援在串流中搜尋"
+
+#: ../client/gdaemonfileinputstream.c:1237
+msgid "The query info operation is not supported"
+msgstr "不支援此查詢資訊的操作"
+
+#: ../client/gdaemonfileoutputstream.c:991
+#, c-format
+msgid "Query info not supported on stream"
+msgstr "串流不支援查詢資訊"
+
+#: ../client/gdaemonvfs.c:830
+#, c-format
+msgid "Error while getting mount info: %s"
+msgstr "取得掛載資訊時發生錯誤:%s"
+
+#: ../client/gvfsdaemondbus.c:568 ../client/gvfsdaemondbus.c:999
+#, c-format
+msgid "Error connecting to daemon: %s"
+msgstr "連線到伺服程式發生錯誤:%s"
+
+#: ../client/gvfsiconloadable.c:145
+msgid "Invalid return value from open_icon_for_read"
+msgstr "從 open_icon_for_read 傳回無效的數值"
+
+#: ../common/gsysutils.c:136
+#, c-format
+msgid "Error creating socket: %s"
+msgstr "建立 socket 時發生錯誤:%s"
+
+#: ../common/gsysutils.c:174
+#, c-format
+msgid "Error connecting to socket: %s"
+msgstr "連線至 socket 時發生錯誤:%s"
+
+#: ../common/gvfsdaemonprotocol.c:454
+msgid "Invalid file info format"
+msgstr "無效的檔案資訊格式"
+
+#: ../common/gvfsdaemonprotocol.c:471
+msgid "Invalid attribute info list content"
+msgstr "無效的屬性資訊清單內容"
+
+#: ../common/gvfsdnssdresolver.c:208
+#, c-format
+msgid "Error initializing Avahi: %s"
+msgstr "初始化 Avahi 時發生錯誤:%s"
+
+#: ../common/gvfsdnssdresolver.c:254
+#, c-format
+msgid "Error creating Avahi resolver: %s"
+msgstr "建立 Avahi 解析器時發生錯誤:%s"
+
+#: ../common/gvfsdnssdresolver.c:1094
+#, c-format
+msgid "Error resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析網域「%3$s」上服務「%2$s」的「%1$s」時發生錯誤"
+
+#: ../common/gvfsdnssdresolver.c:1114
+#, c-format
+msgid ""
+"Error resolving \"%s\" service \"%s\" on domain \"%s\". One or more TXT "
+"records are missing. Keys required: \"%s\"."
+msgstr ""
+"解析網域「%3$s」上服務「%2$s」的「%1$s」時發生錯誤。一或多個 TXT 紀錄遺失。需"
+"要設定鍵:「%4$s」"
+
+#: ../common/gvfsdnssdresolver.c:1126
+#, c-format
+msgid "Timed out resolving \"%s\" service \"%s\" on domain \"%s\""
+msgstr "解析網域「%3$s」上服務「%2$s」的「%1$s」逾時"
+
+#: ../common/gvfsdnssdutils.c:233 ../common/gvfsdnssdutils.c:263
+#: ../common/gvfsdnssdutils.c:280
+#, c-format
+msgid "Malformed dns-sd encoded_triple '%s'"
+msgstr ""
+
+#: ../common/gvfsicon.c:250
+#, c-format
+msgid "Can't handle version %d of GVfsIcon encoding"
+msgstr "不能處理 GVfsIcon 編碼的版本 %d"
+
+#: ../common/gvfsicon.c:260
+msgid "Malformed input data for GVfsIcon"
+msgstr "GVfsIcon 的輸入資料格式不良"
+
+#: ../daemon/daemon-main.c:63 ../daemon/daemon-main.c:206
+#, c-format
+msgid "Error connecting to D-Bus: %s"
+msgstr "連線到 D-Bus 時發生錯誤:%s"
+
+#. translators: This is the default daemon's application name,
+#. * the %s is the type of the backend, like "ftp"
+#: ../daemon/daemon-main.c:78
+#, c-format
+msgid "%s Filesystem Service"
+msgstr "%s 檔案系統服務"
+
+#: ../daemon/daemon-main.c:97
+#, c-format
+msgid "Error: %s"
+msgstr "錯誤:%s"
+
+#: ../daemon/daemon-main.c:131
+#, c-format
+msgid "Usage: %s --spawner dbus-id object_path"
+msgstr "用法:%s --spawner dbus-id object_path"
+
+#: ../daemon/daemon-main.c:155 ../daemon/daemon-main.c:173
+#, c-format
+msgid "Usage: %s key=value key=value ..."
+msgstr "用法: %s key=value key=value ..."
+
+#: ../daemon/daemon-main.c:171
+#, c-format
+msgid "No mount type specified"
+msgstr "未指定掛載類型"
+
+#: ../daemon/daemon-main.c:241
+#, c-format
+msgid "mountpoint for %s already running"
+msgstr "%s 的掛載點已在使用中"
+
+#: ../daemon/daemon-main.c:252
+msgid "error starting mount daemon"
+msgstr "啟動掛載伺服程式的發生錯誤"
+
+#. FIXME: this should really be "/ in %s", but can't change
+#. due to string freeze.
+#. Translators: This is the name of the root of an sftp share, like "/ on <hostname>"
+#: ../daemon/gvfsbackendarchive.c:315 ../daemon/gvfsbackendftp.c:1094
+#: ../daemon/gvfsbackendsftp.c:1903
+#, c-format
+msgid "/ on %s"
+msgstr "/ 於 %s"
+
+#: ../daemon/gvfsbackendarchive.c:515 ../daemon/gvfsbackendftp.c:1640
+#: ../daemon/gvfsbackendsftp.c:1566
+msgid "No hostname specified"
+msgstr "未指定主機名稱"
+
+#: ../daemon/gvfsbackendarchive.c:526 ../daemon/gvfsbackendarchive.c:555
+#: ../daemon/gvfsbackenddav.c:1591 ../daemon/gvfsbackendhttp.c:306
+#: ../daemon/gvfsbackendobexftp.c:836 ../daemon/gvfsbackendobexftp.c:852
+#: ../daemon/gvfsbackendobexftp.c:871 ../daemon/gvfsbackendsmb.c:641
+msgid "Invalid mount spec"
+msgstr "無效的掛載資料"
+
+#: ../daemon/gvfsbackendarchive.c:636 ../daemon/gvfsbackendarchive.c:686
+#: ../daemon/gvfsbackendarchive.c:715 ../daemon/gvfsbackendcdda.c:921
+#: ../daemon/gvfsbackendcomputer.c:572 ../daemon/gvfsbackenddnssd.c:398
+#: ../daemon/gvfsbackendftp.c:2262 ../daemon/gvfsbackendnetwork.c:646
+#: ../daemon/gvfsbackendsmbbrowse.c:1085 ../daemon/gvfsbackendsmbbrowse.c:1152
+#: ../daemon/gvfsbackendsmbbrowse.c:1323 ../daemon/gvfsbackendsmbbrowse.c:1392
+#, c-format
+msgid "File doesn't exist"
+msgstr "檔案不存在"
+
+#: ../daemon/gvfsbackendarchive.c:724 ../daemon/gvfsbackendburn.c:680
+#: ../daemon/gvfsbackendcomputer.c:651 ../daemon/gvfsbackenddnssd.c:445
+#: ../daemon/gvfsbackendftp.c:1043 ../daemon/gvfsbackendnetwork.c:693
+msgid "The file is not a directory"
+msgstr "該檔案不是目錄"
+
+#. Translators: This is the name of the backend
+#: ../daemon/gvfsbackendburn.c:346
+msgid "Burn"
+msgstr "燒錄"
+
+#: ../daemon/gvfsbackendburn.c:376
+msgid "Unable to create temporary directory"
+msgstr "無法建立暫存目錄"
+
+#: ../daemon/gvfsbackendburn.c:405 ../daemon/gvfsbackendburn.c:416
+#: ../daemon/gvfsbackendburn.c:451 ../daemon/gvfsbackendburn.c:672
+#: ../daemon/gvfsbackendburn.c:719 ../daemon/gvfsbackendburn.c:745
+#: ../daemon/gvfsbackendburn.c:783 ../daemon/gvfsbackendgphoto2.c:1063
+#: ../daemon/gvfsbackendgphoto2.c:1916 ../daemon/gvfsbackendgphoto2.c:2626
+#: ../daemon/gvfsbackendtrash.c:216
+#, c-format
+msgid "No such file or directory"
+msgstr "沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendburn.c:425 ../daemon/gvfsbackenddav.c:2183
+msgid "Directory not empty"
+msgstr "目錄不是空的"
+
+#: ../daemon/gvfsbackendburn.c:459 ../daemon/gvfsbackendburn.c:906
+#: ../daemon/gvfsbackendobexftp.c:1783
+msgid "Can't copy file over directory"
+msgstr "不能將檔案複製到目錄上"
+
+#. Translators: this is the display name of the backend
+#: ../daemon/gvfsbackendburn.c:651
+msgid "CD/DVD Creator"
+msgstr "CD/DVD 製作程式"
+
+#: ../daemon/gvfsbackendburn.c:755 ../daemon/gvfsbackendburn.c:791
+#: ../daemon/gvfsbackendburn.c:926 ../daemon/gvfsbackendgphoto2.c:2700
+msgid "File exists"
+msgstr "檔案已存在"
+
+#: ../daemon/gvfsbackendburn.c:829 ../daemon/gvfsjobcloseread.c:112
+#: ../daemon/gvfsjobclosewrite.c:120 ../daemon/gvfsjobcopy.c:169
+#: ../daemon/gvfsjobcreatemonitor.c:140 ../daemon/gvfsjobcreatemonitor.c:151
+#: ../daemon/gvfsjobcreatemonitor.c:174 ../daemon/gvfsjobcreatemonitor.c:192
+#: ../daemon/gvfsjobdelete.c:122 ../daemon/gvfsjobenumerate.c:256
+#: ../daemon/gvfsjobmakedirectory.c:122 ../daemon/gvfsjobmount.c:109
+#: ../daemon/gvfsjobmountmountable.c:156 ../daemon/gvfsjobmove.c:168
+#: ../daemon/gvfsjobopenforread.c:130 ../daemon/gvfsjobopenforwrite.c:148
+#: ../daemon/gvfsjobopenforwrite.c:162 ../daemon/gvfsjobopenforwrite.c:176
+#: ../daemon/gvfsjobopeniconforread.c:120 ../daemon/gvfsjobpull.c:173
+#: ../daemon/gvfsjobpush.c:173 ../daemon/gvfsjobqueryattributes.c:135
+#: ../daemon/gvfsjobqueryfsinfo.c:131 ../daemon/gvfsjobqueryinfo.c:149
+#: ../daemon/gvfsjobread.c:120 ../daemon/gvfsjobseekread.c:119
+#: ../daemon/gvfsjobseekwrite.c:119 ../daemon/gvfsjobsetattribute.c:150
+#: ../daemon/gvfsjobsetdisplayname.c:127 ../daemon/gvfsjobtrash.c:122
+#: ../daemon/gvfsjobunmountmountable.c:132
+#: ../daemon/gvfsjobunmountmountable.c:146 ../daemon/gvfsjobwrite.c:120
+msgid "Operation not supported by backend"
+msgstr "後端不支援此操作"
+
+#: ../daemon/gvfsbackendburn.c:854
+msgid "No such file or directory in target path"
+msgstr "在目標路徑沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendburn.c:877 ../daemon/gvfsbackendobexftp.c:1752
+msgid "Can't copy directory over directory"
+msgstr "不能將目錄複製到目錄上"
+
+#: ../daemon/gvfsbackendburn.c:886 ../daemon/gvfsbackendobexftp.c:1760
+#: ../daemon/gvfsbackendobexftp.c:1791
+msgid "Target file exists"
+msgstr "目標檔案已存在"
+
+#: ../daemon/gvfsbackendburn.c:893 ../daemon/gvfsbackendobexftp.c:1767
+msgid "Can't recursively copy directory"
+msgstr "不能遞廻複製目錄"
+
+#: ../daemon/gvfsbackendburn.c:952 ../daemon/gvfsbackendcomputer.c:731
+#: ../daemon/gvfsbackendgphoto2.c:2281 ../daemon/gvfsbackendgphoto2.c:2490
+#: ../daemon/gvfsbackendgphoto2.c:2587 ../daemon/gvfsbackendgphoto2.c:2679
+msgid "Not supported"
+msgstr "不支援"
+
+#: ../daemon/gvfsbackendcdda.c:299 ../daemon/gvfsbackendgphoto2.c:1303
+msgid "Cannot connect to the system bus"
+msgstr "不能連線到系統匯流排"
+
+#: ../daemon/gvfsbackendcdda.c:310 ../daemon/gvfsbackendgphoto2.c:1315
+msgid "Cannot create libhal context"
+msgstr "不能建立 libhal 脈絡"
+
+#: ../daemon/gvfsbackendcdda.c:324 ../daemon/gvfsbackendgphoto2.c:1328
+msgid "Cannot initialize libhal"
+msgstr "不能初始化 libhal"
+
+#: ../daemon/gvfsbackendcdda.c:339 ../daemon/gvfsbackendcdda.c:415
+msgid "No drive specified"
+msgstr "未指定裝置"
+
+#: ../daemon/gvfsbackendcdda.c:355
+#, c-format
+msgid "Cannot find drive %s"
+msgstr "找不到到裝置 %s"
+
+#: ../daemon/gvfsbackendcdda.c:368
+#, c-format
+msgid "Drive %s does not contain audio files"
+msgstr "裝置 %s 中不包含音樂檔案"
+
+#. Translator: %s is the device the disc is inserted into
+#: ../daemon/gvfsbackendcdda.c:377
+#, c-format
+msgid "cdda mount on %s"
+msgstr "cdda 掛載於 %s"
+
+#: ../daemon/gvfsbackendcdda.c:378 ../daemon/gvfsbackendcdda.c:895
+#: ../monitor/hal/ghalmount.c:435 ../monitor/hal/ghalvolume.c:233
+#: ../monitor/hal/ghalvolume.c:254
+#, c-format
+msgid "Audio Disc"
+msgstr "音樂光碟"
+
+#: ../daemon/gvfsbackendcdda.c:439 ../daemon/gvfsbackendgphoto2.c:1550
+#, c-format
+msgid "File system is busy: %d open file"
+msgid_plural "File system is busy: %d open files"
+msgstr[0] "檔案系統忙碌中:開啟了 %d 個檔案"
+
+#: ../daemon/gvfsbackendcdda.c:630
+#, c-format
+msgid "No such file %s on drive %s"
+msgstr "磁碟 %2$s 中沒有檔案 %1$s"
+
+#. Translators: paranoia is the name of the cd audio reading library
+#: ../daemon/gvfsbackendcdda.c:739
+#, c-format
+msgid "Error from 'paranoia' on drive %s"
+msgstr "來自磁碟 %s 上的「paranoia」的錯誤"
+
+#: ../daemon/gvfsbackendcdda.c:802
+#, c-format
+msgid "Error seeking in stream on drive %s"
+msgstr "在磁碟 %s 上搜尋串流發生錯誤"
+
+#: ../daemon/gvfsbackendcdda.c:914 ../daemon/gvfsbackendgphoto2.c:1606
+#, c-format
+msgid "No such file"
+msgstr "沒有這個檔案"
+
+#: ../daemon/gvfsbackendcdda.c:928
+#, c-format
+msgid "The file does not exist or isn't an audio track"
+msgstr "檔案不存在或不是音軌"
+
+#: ../daemon/gvfsbackendcdda.c:1034
+msgid "Audio CD Filesystem Service"
+msgstr "音樂 CD 檔案系統服務"
+
+#: ../daemon/gvfsbackendcomputer.c:179 ../daemon/gvfsbackendcomputer.c:693
+msgid "Computer"
+msgstr "電腦"
+
+#: ../daemon/gvfsbackendcomputer.c:466
+msgid "Filesystem"
+msgstr "檔案系統"
+
+#: ../daemon/gvfsbackendcomputer.c:590 ../daemon/gvfsbackendgphoto2.c:1598
+#: ../daemon/gvfsbackendobexftp.c:1046 ../daemon/gvfsbackendsmb.c:684
+#: ../daemon/gvfsbackendtrash.c:232
+#, c-format
+msgid "Can't open directory"
+msgstr "不能開啟目錄"
+
+#: ../daemon/gvfsbackendcomputer.c:594
+msgid "Can't open mountable file"
+msgstr "不能開啟可掛載式檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:779 ../daemon/gvfsbackendsftp.c:1044
+#, c-format
+msgid "Internal error: %s"
+msgstr "內部的錯誤:%s"
+
+#: ../daemon/gvfsbackendcomputer.c:811 ../daemon/gvfsbackendcomputer.c:928
+msgid "Can't mount file"
+msgstr "不能掛載檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:823
+msgid "No media in the drive"
+msgstr "裝置中沒有媒體"
+
+#: ../daemon/gvfsbackendcomputer.c:880 ../daemon/gvfsbackendcomputer.c:971
+#: ../daemon/gvfsbackendcomputer.c:1071
+msgid "Not a mountable file"
+msgstr "不是可掛載式檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:986
+msgid "Can't unmount file"
+msgstr "不能卸載檔案"
+
+#: ../daemon/gvfsbackendcomputer.c:1102
+msgid "Can't eject file"
+msgstr "不能退出檔案"
+
+#: ../daemon/gvfsbackenddav.c:526 ../daemon/gvfsbackenddav.c:1658
+#: ../daemon/gvfsbackendhttp.c:252
+#, c-format
+msgid "HTTP Error: %s"
+msgstr "HTTP 錯誤: %s"
+
+#: ../daemon/gvfsbackenddav.c:543
+msgid "Could not parse response"
+msgstr "無法解析回應"
+
+#: ../daemon/gvfsbackenddav.c:552
+msgid "Empty response"
+msgstr "空白的回應"
+
+#: ../daemon/gvfsbackenddav.c:560
+msgid "Unexpected reply from server"
+msgstr "來自伺服器未預期的回應"
+
+#: ../daemon/gvfsbackenddav.c:1179 ../daemon/gvfsbackenddav.c:1798
+msgid "Response invalid"
+msgstr "回應無效"
+
+#: ../daemon/gvfsbackenddav.c:1322
+msgid "WebDAV share"
+msgstr "WebDAV 分享"
+
+#: ../daemon/gvfsbackenddav.c:1324
+#, c-format
+msgid "Enter password for %s"
+msgstr "輸入 %s 的密碼 "
+
+#: ../daemon/gvfsbackenddav.c:1327
+msgid "Please enter proxy password"
+msgstr "請輸入代理伺服器密碼"
+
+#: ../daemon/gvfsbackenddav.c:1662 ../daemon/gvfsbackenddav.c:1666
+msgid "Not a WebDAV enabled share"
+msgstr "不是使用 WebDAV 的分享"
+
+#: ../daemon/gvfsbackenddav.c:1694
+#, c-format
+msgid "WebDAV on %s"
+msgstr "WebDAV 於 %s"
+
+#: ../daemon/gvfsbackenddav.c:1754 ../daemon/gvfsbackenddav.c:1827
+msgid "Could not create request"
+msgstr "無法建立要求"
+
+#: ../daemon/gvfsbackenddav.c:1890 ../daemon/gvfsbackenddav.c:2143
+#: ../daemon/gvfsbackenddav.c:2254 ../daemon/gvfsbackendftp.c:1860
+#: ../daemon/gvfsbackendftp.c:2526 ../daemon/gvfsbackendsftp.c:3588
+#: ../daemon/gvfsbackendsmb.c:1912
+msgid "Target file already exists"
+msgstr "目標檔案已存在"
+
+#: ../daemon/gvfsbackenddav.c:1963 ../daemon/gvfsbackendsftp.c:2836
+#: ../daemon/gvfsbackendsmb.c:1074
+msgid "The file was externally modified"
+msgstr "該檔案已被外部程式修改過"
+
+#: ../daemon/gvfsbackenddav.c:1994 ../daemon/gvfsbackendsmb.c:1110
+#: ../daemon/gvfsbackendsmb.c:1929
+msgid "Backup file creation failed"
+msgstr "建立備份檔案失敗"
+
+#. "separate": a link to dns-sd://local/
+#: ../daemon/gvfsbackenddnssd.c:492 ../daemon/gvfsbackendnetwork.c:393
+msgid "Local Network"
+msgstr "本地端網路"
+
+#: ../daemon/gvfsbackenddnssd.c:736 ../daemon/gvfsbackendnetwork.c:797
+msgid "Can't monitor file or directory."
+msgstr "不能監控檔案或目錄。"
+
+#. TODO: Names, etc
+#: ../daemon/gvfsbackenddnssd.c:754
+msgid "Dns-SD"
+msgstr "Dns-SD"
+
+#: ../daemon/gvfsbackenddnssd.c:755 ../daemon/gvfsbackendnetwork.c:732
+#: ../daemon/gvfsbackendnetwork.c:882 ../daemon/gvfsbackendnetwork.c:883
+msgid "Network"
+msgstr "網路"
+
+#: ../daemon/gvfsbackendftp.c:252
+msgid "Accounts are unsupported"
+msgstr "帳號不被支援"
+
+#: ../daemon/gvfsbackendftp.c:256
+msgid "Host closed connection"
+msgstr "主機關閉連線"
+
+#: ../daemon/gvfsbackendftp.c:260
+msgid "Cannot open data connection. Maybe your firewall prevents this?"
+msgstr "無法開啟資料連線。也許您的防火牆阻擋了它?"
+
+#: ../daemon/gvfsbackendftp.c:264
+msgid "Data connection closed"
+msgstr "資料連線已關閉"
+
+#: ../daemon/gvfsbackendftp.c:271 ../daemon/gvfsbackendftp.c:275
+msgid "Operation failed"
+msgstr "操作已失敗"
+
+#: ../daemon/gvfsbackendftp.c:280
+msgid "No space left on server"
+msgstr "伺服器中沒有剩餘空間"
+
+#: ../daemon/gvfsbackendftp.c:288 ../daemon/gvfsbackendsftp.c:3897
+#: ../daemon/gvfsbackendsmb.c:1576
+msgid "Operation unsupported"
+msgstr "操作不被支援"
+
+#: ../daemon/gvfsbackendftp.c:292 ../daemon/gvfsbackendsftp.c:296
+msgid "Permission denied"
+msgstr "權限不足"
+
+#: ../daemon/gvfsbackendftp.c:296
+msgid "Page type unknown"
+msgstr "頁面類型不明"
+
+#: ../daemon/gvfsbackendftp.c:300 ../daemon/gvfsbackendftp.c:2372
+msgid "Invalid filename"
+msgstr "無效的檔案名稱"
+
+#: ../daemon/gvfsbackendftp.c:304 ../daemon/gvfsbackendftp.c:380
+#: ../daemon/gvfsbackendftp.c:409 ../daemon/gvfsbackendftp.c:428
+#: ../daemon/gvfsbackendftp.c:441 ../daemon/gvfsbackendftp.c:929
+msgid "Invalid reply"
+msgstr "無效的回應"
+
+#: ../daemon/gvfsbackendftp.c:548
+msgid "broken transmission"
+msgstr "損壞的傳輸"
+
+#: ../daemon/gvfsbackendftp.c:710 ../daemon/gvfsbackendftp.c:851
+msgid "Could not connect to host"
+msgstr "無法連線至主機"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1494
+#, c-format
+msgid "Enter password for ftp as %s on %s"
+msgstr "輸入 %s 在 %s 上的 ftp 密碼 "
+
+#. translators: %s here is the hostname
+#: ../daemon/gvfsbackendftp.c:1497
+#, c-format
+msgid "Enter password for ftp on %s"
+msgstr "輸入 %s 的 ftp 密碼 "
+
+#: ../daemon/gvfsbackendftp.c:1523 ../daemon/gvfsbackendsftp.c:881
+#: ../daemon/gvfsbackendsmb.c:599 ../daemon/gvfsbackendsmbbrowse.c:986
+msgid "Password dialog cancelled"
+msgstr "密碼對話盒已被取消"
+
+#: ../daemon/gvfsbackendftp.c:1602
+#, c-format
+msgid "ftp on %s"
+msgstr "ftp 於 %s"
+
+#. Translators: the first %s is the username, the second the host name
+#: ../daemon/gvfsbackendftp.c:1606
+#, c-format
+msgid "ftp as %s on %s"
+msgstr "以 %s 登入 %s 的 ftp"
+
+#: ../daemon/gvfsbackendftp.c:1690 ../daemon/gvfsbackendsftp.c:1967
+#: ../daemon/gvfsbackendsftp.c:3579
+msgid "File is directory"
+msgstr "檔案是目錄"
+
+#: ../daemon/gvfsbackendftp.c:1912 ../daemon/gvfsbackendftp.c:2487
+msgid "backups not supported yet"
+msgstr "備份尚未支援"
+
+#: ../daemon/gvfsbackendftp.c:1989
+msgid "filename too long"
+msgstr "檔案名稱太長"
+
+#: ../daemon/gvfsbackendftp.c:2506
+msgid "Invalid destination filename"
+msgstr "無效的目的端檔案名稱"
+
+#: ../daemon/gvfsbackendgphoto2.c:486
+#, c-format
+msgid "%s: %d: Directory or file exists"
+msgstr "%s:%d:目錄或檔案已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:493
+#, c-format
+msgid "%s: %d: No such file or directory"
+msgstr "%s:%d:沒有這個檔案或目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:499
+#, c-format
+msgid "%s: %d: Invalid filename"
+msgstr "%s:%d:無效的檔案名稱"
+
+#: ../daemon/gvfsbackendgphoto2.c:505
+#, c-format
+msgid "%s: %d: Not Supported"
+msgstr "%s:%d:不支援"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:675
+#, c-format
+msgid "Digital Camera (%s)"
+msgstr "數位相機 (%s)"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:823 ../monitor/gphoto2/ggphoto2volume.c:183
+#, c-format
+msgid "%s Camera"
+msgstr "%s 照相機"
+
+#. Translator: %s is the vendor name, e.g. Panasonic
+#. Translators: %s is the device vendor
+#: ../daemon/gvfsbackendgphoto2.c:826 ../monitor/gphoto2/ggphoto2volume.c:178
+#, c-format
+msgid "%s Audio Player"
+msgstr "%s 音樂播放機"
+
+#: ../daemon/gvfsbackendgphoto2.c:835 ../monitor/gphoto2/ggphoto2volume.c:192
+msgid "Camera"
+msgstr "照相機"
+
+#: ../daemon/gvfsbackendgphoto2.c:837 ../monitor/gphoto2/ggphoto2volume.c:190
+msgid "Audio Player"
+msgstr "音樂播放機"
+
+#: ../daemon/gvfsbackendgphoto2.c:1343
+msgid "No device specified"
+msgstr "未指定裝置"
+
+#: ../daemon/gvfsbackendgphoto2.c:1360
+msgid "Cannot create gphoto2 context"
+msgstr "不能建立 gphoto2 脈絡"
+
+#: ../daemon/gvfsbackendgphoto2.c:1370
+msgid "Error creating camera"
+msgstr "建立攝影機發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1383 ../daemon/gvfsbackendgphoto2.c:1393
+msgid "Error loading device information"
+msgstr "載入裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1405
+msgid "Error looking up device information"
+msgstr "尋找裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1415
+msgid "Error getting device information"
+msgstr "取得裝置資訊時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1428
+msgid "Error setting up camera communications port"
+msgstr "設定攝影機通訊埠時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1439
+msgid "Error initializing camera"
+msgstr "初始化攝影機發生錯誤"
+
+#. Translator: %s represents the device, e.g. usb:001,042
+#: ../daemon/gvfsbackendgphoto2.c:1447
+#, c-format
+msgid "gphoto2 mount on %s"
+msgstr "gphoto2 掛載於 %s"
+
+#: ../daemon/gvfsbackendgphoto2.c:1522
+msgid "No camera specified"
+msgstr "未指定攝影機"
+
+#: ../daemon/gvfsbackendgphoto2.c:1614
+msgid "Error creating file object"
+msgstr "建立檔案物件發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1629
+msgid "Error getting file"
+msgstr "讀取檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1639
+msgid "Error getting data from file"
+msgstr "從檔案取得資料時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1696
+#, c-format
+msgid "Malformed icon identifier '%s'"
+msgstr "圖示識別符「%s」格式不良"
+
+#: ../daemon/gvfsbackendgphoto2.c:1772 ../daemon/gvfsbackendgphoto2.c:2950
+#, c-format
+msgid "Error seeking in stream on camera %s"
+msgstr "在攝影機 %s 上搜尋串流發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:1910 ../daemon/gvfsbackendsmbbrowse.c:1388
+msgid "Not a directory"
+msgstr "不是一個目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:1943
+msgid "Failed to get folder list"
+msgstr "取得資料夾清單失敗"
+
+#: ../daemon/gvfsbackendgphoto2.c:2008
+msgid "Failed to get file list"
+msgstr "取得檔案清單失敗"
+
+#: ../daemon/gvfsbackendgphoto2.c:2293
+msgid "Error creating directory"
+msgstr "建立目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2502
+msgid "Name already exists"
+msgstr "名稱已存在"
+
+#: ../daemon/gvfsbackendgphoto2.c:2513 ../daemon/gvfsbackendgphoto2.c:3141
+msgid "New name too long"
+msgstr "新的名稱太長"
+
+#: ../daemon/gvfsbackendgphoto2.c:2523 ../daemon/gvfsbackendgphoto2.c:3152
+msgid "Error renaming dir"
+msgstr "重新命名目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2536 ../daemon/gvfsbackendgphoto2.c:3165
+msgid "Error renaming file"
+msgstr "重新命名檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2599
+#, c-format
+msgid "Directory '%s' is not empty"
+msgstr "目錄「%s」不是空的"
+
+#: ../daemon/gvfsbackendgphoto2.c:2610
+msgid "Error deleting directory"
+msgstr "刪除目錄時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2636
+msgid "Error deleting file"
+msgstr "刪除檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:2689
+msgid "Can't write to directory"
+msgstr "不能寫入至目錄"
+
+#: ../daemon/gvfsbackendgphoto2.c:2736
+msgid "Cannot allocate new file to append to"
+msgstr "不能分配新檔案加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2751
+msgid "Cannot read file to append to"
+msgstr "不能讀取檔案加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:2762
+msgid "Cannot get data of file to append to"
+msgstr "不能取得檔案的資料加入到"
+
+#: ../daemon/gvfsbackendgphoto2.c:3049
+msgid "Error writing file"
+msgstr "寫入檔案時發生錯誤"
+
+#: ../daemon/gvfsbackendgphoto2.c:3097
+msgid "Not supported (not same directory)"
+msgstr "不支援(不同目錄)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3109
+msgid "Not supported (src is dir, dst is dir)"
+msgstr "不支援(來源是目錄,目的也是目錄)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3117
+msgid "Not supported (src is dir, dst is existing file)"
+msgstr "不支援(來源是目錄,目的是既存的檔案)"
+
+#: ../daemon/gvfsbackendgphoto2.c:3129
+msgid "Not supported (src is file, dst is dir)"
+msgstr "不支援(來源是檔案,目的是目錄)"
+
+#: ../daemon/gvfsbackendhttp.c:248
+#, c-format
+msgid "HTTP Client Error: %s"
+msgstr "HTTP 客戶端錯誤:%s"
+
+#: ../daemon/gvfsbackendhttp.c:570 ../daemon/gvfsbackendsftp.c:1891
+#: ../daemon/gvfsbackendsmb.c:1337 ../daemon/gvfsdaemonutils.c:211
+msgid " (invalid encoding)"
+msgstr "(無效的編碼)"
+
+#: ../daemon/gvfsbackendlocaltest.c:853
+msgid "Directory notification not supported"
+msgstr "不支援目錄通知"
+
+#. smb:/// root link
+#: ../daemon/gvfsbackendnetwork.c:269 ../daemon/gvfsbackendsmbbrowse.c:885
+msgid "Windows Network"
+msgstr "Windows 網路"
+
+#. Translators: this is the friendly name of the 'network://' backend that
+#. * shows computers in your local network.
+#: ../daemon/gvfsbackendnetwork.c:931
+msgid "Network Location Monitor"
+msgstr "網路位置監視器"
+
+#. Set the mountspec according to original uri, no matter whether user changes
+#. credentials during mount loop. Nautilus and other gio clients depend
+#. on correct mountspec, setting it to real (different) credentials would
+#. lead to G_IO_ERROR_NOT_MOUNTED errors
+#.
+#. Translators: This is "<sharename> on <servername>" and is used as name for an SMB share
+#: ../daemon/gvfsbackendobexftp.c:656 ../daemon/gvfsbackendsmb.c:538
+#: ../daemon/gvfsbackendsmb.c:1330
+#, c-format
+msgid "%s on %s"
+msgstr "%s 於 %s"
+
+#: ../daemon/gvfsbackendobexftp.c:865
+msgid "USB support missing. Please contact your software vendor"
+msgstr "USB 支援遺失。請連絡您的軟體廠商"
+
+#: ../daemon/gvfsbackendobexftp.c:985
+msgid "Connection to the device lost"
+msgstr "到裝置的連線已失去"
+
+#: ../daemon/gvfsbackendobexftp.c:1482
+msgid "Device requires a software update"
+msgstr "裝置要求更新軟體"
+
+#: ../daemon/gvfsbackendsftp.c:288
+msgid "ssh program unexpectedly exited"
+msgstr "ssh 程式意外的中止了"
+
+#: ../daemon/gvfsbackendsftp.c:303
+msgid "Hostname not known"
+msgstr "主機名稱不明"
+
+#: ../daemon/gvfsbackendsftp.c:310
+msgid "No route to host"
+msgstr "沒有路由可到主機"
+
+#: ../daemon/gvfsbackendsftp.c:317
+msgid "Connection refused by server"
+msgstr "連線被伺服器拒絕"
+
+#: ../daemon/gvfsbackendsftp.c:324
+msgid "Host key verification failed"
+msgstr "驗證主機金鑰失敗"
+
+#: ../daemon/gvfsbackendsftp.c:407
+msgid "Unable to spawn ssh program"
+msgstr "無法呼叫 ssh 程式"
+
+#: ../daemon/gvfsbackendsftp.c:423
+#, c-format
+msgid "Unable to spawn ssh program: %s"
+msgstr "無法呼叫 ssh 程式:%s"
+
+#: ../daemon/gvfsbackendsftp.c:535 ../daemon/gvfsbackendsftp.c:787
+msgid "Timed out when logging in"
+msgstr "登入逾時時間"
+
+#: ../daemon/gvfsbackendsftp.c:865
+msgid "Enter passphrase for key"
+msgstr "輸入金鑰的密語 "
+
+#: ../daemon/gvfsbackendsftp.c:867
+msgid "Enter password"
+msgstr "輸入密碼"
+
+#: ../daemon/gvfsbackendsftp.c:928
+msgid "Can't send password"
+msgstr "不能傳送密碼"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Log In Anyway"
+msgstr "強制登入"
+
+#: ../daemon/gvfsbackendsftp.c:936
+msgid "Cancel Login"
+msgstr "取消登入"
+
+#: ../daemon/gvfsbackendsftp.c:946
+#, c-format
+msgid ""
+"The identity of the remote computer (%s) is unknown.\n"
+"This happens when you log in to a computer the first time.\n"
+"\n"
+"The identity sent by the remote computer is %s. If you want to be absolutely "
+"sure it is safe to continue, contact the system administrator."
+msgstr ""
+"遠端電腦 (%s) 的識別不明。\n"
+"這通常發生在您第一次登入電腦的時候。\n"
+"\n"
+"由遠端電腦傳送的識別為 %s。如果您想要完全確定繼續是安全的,請連絡系統管理者。"
+
+#: ../daemon/gvfsbackendsftp.c:966
+msgid "Login dialog cancelled"
+msgstr "登入對話盒已被取消"
+
+#: ../daemon/gvfsbackendsftp.c:986
+msgid "Can't send host identity confirmation"
+msgstr "不能傳送主機識別確認"
+
+#: ../daemon/gvfsbackendsftp.c:1479 ../daemon/gvfsbackendsftp.c:1502
+msgid "Protocol error"
+msgstr "通訊協定錯誤"
+
+#. Translators: This is the name of an sftp share, like "sftp for <user>on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1527
+#, c-format
+msgid "sftp for %s on %s"
+msgstr "sftp 以 %s 於 %s"
+
+#. Translators: This is the name of an sftp share, like "sftp on <hostname>"
+#: ../daemon/gvfsbackendsftp.c:1530
+#, c-format
+msgid "sftp on %s"
+msgstr "sftp 於 %s"
+
+#: ../daemon/gvfsbackendsftp.c:1556
+msgid "Unable to find supported ssh command"
+msgstr "找不到支援的 ssh 指令"
+
+#: ../daemon/gvfsbackendsftp.c:1976
+msgid "Failure"
+msgstr "失敗"
+
+#: ../daemon/gvfsbackendsftp.c:2032 ../daemon/gvfsbackendsftp.c:2111
+#: ../daemon/gvfsbackendsftp.c:2122 ../daemon/gvfsbackendsftp.c:2178
+#: ../daemon/gvfsbackendsftp.c:2264 ../daemon/gvfsbackendsftp.c:2314
+#: ../daemon/gvfsbackendsftp.c:2360 ../daemon/gvfsbackendsftp.c:2435
+#: ../daemon/gvfsbackendsftp.c:2542 ../daemon/gvfsbackendsftp.c:2582
+#: ../daemon/gvfsbackendsftp.c:2632 ../daemon/gvfsbackendsftp.c:2701
+#: ../daemon/gvfsbackendsftp.c:2721 ../daemon/gvfsbackendsftp.c:2873
+#: ../daemon/gvfsbackendsftp.c:2898 ../daemon/gvfsbackendsftp.c:2953
+#: ../daemon/gvfsbackendsftp.c:3010 ../daemon/gvfsbackendsftp.c:3281
+#: ../daemon/gvfsbackendsftp.c:3348 ../daemon/gvfsbackendsftp.c:3477
+#: ../daemon/gvfsbackendsftp.c:3512 ../daemon/gvfsbackendsftp.c:3540
+#: ../daemon/gvfsbackendsftp.c:3648 ../daemon/gvfsbackendsftp.c:3702
+#: ../daemon/gvfsbackendsftp.c:3736 ../daemon/gvfsbackendsftp.c:3770
+#: ../daemon/gvfsbackendsftp.c:3785 ../daemon/gvfsbackendsftp.c:3800
+#: ../daemon/gvfsbackendsftp.c:3878
+msgid "Invalid reply received"
+msgstr "收到無效的回應"
+
+#: ../daemon/gvfsbackendsftp.c:2084
+#, c-format
+msgid "Invalid icon_id '%s' in OpenIconForRead"
+msgstr "OpenIconForRead 中有無效的 icon_id 「%s」"
+
+#: ../daemon/gvfsbackendsftp.c:2380
+#, c-format
+msgid "Error creating backup file: %s"
+msgstr "建立備份檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsftp.c:2783
+msgid "Unable to create temporary file"
+msgstr "無法建立暫存檔案"
+
+#: ../daemon/gvfsbackendsftp.c:3574 ../daemon/gvfsbackendsmb.c:1901
+msgid "Can't move directory over directory"
+msgstr "不能將目錄移動至目錄上"
+
+#. translators: First %s is a share name, second is a server name
+#: ../daemon/gvfsbackendsmb.c:222
+#, c-format
+msgid "Password required for share %s on %s"
+msgstr "要分享 %2$s 上的 %1$s 需要密碼"
+
+#: ../daemon/gvfsbackendsmb.c:478 ../daemon/gvfsbackendsmb.c:524
+#: ../daemon/gvfsdaemonutils.c:92
+#, c-format
+msgid "Internal Error (%s)"
+msgstr "內部的錯誤 (%s)"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmb.c:604
+msgid "Failed to mount Windows share"
+msgstr "掛載 Windows 分享失敗"
+
+#: ../daemon/gvfsbackendsmb.c:753 ../daemon/gvfsbackendsmb.c:1209
+msgid "Unsupported seek type"
+msgstr "不支援的搜尋類型"
+
+#: ../daemon/gvfsbackendsmb.c:1273
+#, c-format
+msgid "Backup file creation failed: %s"
+msgstr "建立備份檔案失敗:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1803
+#, c-format
+msgid "Error deleting file: %s"
+msgstr "刪除檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1877
+#, c-format
+msgid "Error moving file: %s"
+msgstr "移動檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1949
+#, c-format
+msgid "Error removing target file: %s"
+msgstr "移除目標檔案時發生錯誤:%s"
+
+#: ../daemon/gvfsbackendsmb.c:1973
+msgid "Can't recursively move directory"
+msgstr "不能循環移動目錄"
+
+#: ../daemon/gvfsbackendsmb.c:2037
+msgid "Windows Shares Filesystem Service"
+msgstr "Windows 分享檔案系統服務"
+
+#. translators: %s is a server name
+#: ../daemon/gvfsbackendsmbbrowse.c:365
+#, c-format
+msgid "Password required for %s"
+msgstr "%s 需要的密碼 "
+
+#. translators: Name for the location that lists the smb shares
+#. availible on a server (%s is the name of the server)
+#: ../daemon/gvfsbackendsmbbrowse.c:893
+#, c-format
+msgid "Windows shares on %s"
+msgstr "Windows 分享於 %s"
+
+#. translators: We tried to mount a windows (samba) share, but failed
+#: ../daemon/gvfsbackendsmbbrowse.c:992
+msgid "Failed to retrieve share list from server"
+msgstr "從伺服器取回分享清單失敗"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1080 ../daemon/gvfsbackendsmbbrowse.c:1126
+msgid "The file is not a mountable"
+msgstr "該檔案是無法掛載的"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1148
+msgid "Not a regular file"
+msgstr "不是正規的檔案"
+
+#: ../daemon/gvfsbackendsmbbrowse.c:1501
+msgid "Windows Network Filesystem Service"
+msgstr "Windows 網路檔案系統服務"
+
+#: ../daemon/gvfsbackendtrash.c:370 ../daemon/gvfsbackendtrash.c:426
+#, c-format
+msgid "The trash folder may not be deleted"
+msgstr "回收筒資料來不能刪除"
+
+#: ../daemon/gvfsbackendtrash.c:387 ../daemon/gvfsbackendtrash.c:440
+#, c-format
+msgid "Items in the trash may not be modified"
+msgstr "回收筒中的項目不能修改"
+
+#. Translators: this is the display name of the backend
+#. translators: This is the name of the backend
+#: ../daemon/gvfsbackendtrash.c:735 ../daemon/gvfsbackendtrash.c:843
+msgid "Trash"
+msgstr "回收筒"
+
+#: ../daemon/gvfsdaemon.c:1032
+msgid "Invalid backend type"
+msgstr "無效的後端類型"
+
+#: ../daemon/gvfsdaemonutils.c:104
+#, c-format
+msgid "Error sending fd: %s"
+msgstr "傳送 fd 時發生錯誤:%s"
+
+#: ../daemon/gvfsjobmakesymlink.c:126
+msgid "Symlinks not supported by backend"
+msgstr "後端不支援符號連結"
+
+#: ../daemon/gvfsjobsetattribute.c:120
+msgid "Invalid dbus message"
+msgstr "無效的 dbus 訊息"
+
+#: ../daemon/main.c:45
+msgid "Replace old daemon."
+msgstr "置換舊的伺服程式。"
+
+#: ../daemon/main.c:46
+msgid "Don't start fuse."
+msgstr "不啟動 fuse。"
+
+#: ../daemon/main.c:58
+msgid "GVFS Daemon"
+msgstr "GVFS 伺服程式"
+
+#: ../daemon/main.c:61
+msgid "Main daemon for GVFS"
+msgstr "GCFS 主伺服程式"
+
+#. Translators: the first %s is the application name,
+#. the second %s is the error message
+#: ../daemon/main.c:76
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: ../daemon/main.c:78 ../programs/gvfs-cat.c:163 ../programs/gvfs-cat.c:176
+#: ../programs/gvfs-copy.c:101 ../programs/gvfs-info.c:364
+#: ../programs/gvfs-ls.c:386 ../programs/gvfs-mkdir.c:59
+#: ../programs/gvfs-move.c:97 ../programs/gvfs-open.c:131
+#: ../programs/gvfs-open.c:144 ../programs/gvfs-save.c:165
+#: ../programs/gvfs-tree.c:251
+#, c-format
+msgid "Try \"%s --help\" for more information."
+msgstr "使用「%s --help」以獲得更多資訊。"
+
+#: ../daemon/mount.c:456
+msgid "Invalid arguments from spawned child"
+msgstr "來自衍生子程序的無效引數"
+
+#: ../daemon/mount.c:767
+#, c-format
+msgid "Automount failed: %s"
+msgstr "自動掛載失敗:%s"
+
+#: ../daemon/mount.c:812 ../daemon/mount.c:886
+msgid "The specified location is not mounted"
+msgstr "指定的位置尚未掛載"
+
+#: ../daemon/mount.c:817
+msgid "The specified location is not supported"
+msgstr "指定的位置不被支援"
+
+#: ../daemon/mount.c:1023
+msgid "Location is already mounted"
+msgstr "該位置已經掛載了"
+
+#: ../daemon/mount.c:1031
+msgid "Location is not mountable"
+msgstr "該位置不是可掛載的"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "CD-ROM Disc"
+msgstr "CD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:40 ../monitor/hal/hal-utils.c:40
+msgid "Blank CD-ROM Disc"
+msgstr "空白 CD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "CD-R Disc"
+msgstr "CD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:41 ../monitor/hal/hal-utils.c:41
+msgid "Blank CD-R Disc"
+msgstr "空白 CD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "CD-RW Disc"
+msgstr "CD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:42 ../monitor/hal/hal-utils.c:42
+msgid "Blank CD-RW Disc"
+msgstr "空白 CD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "DVD-ROM Disc"
+msgstr "DVD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:43 ../monitor/gphoto2/hal-utils.c:45
+#: ../monitor/hal/hal-utils.c:43 ../monitor/hal/hal-utils.c:45
+msgid "Blank DVD-ROM Disc"
+msgstr "空白 DVD-ROM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "DVD-RAM Disc"
+msgstr "DVD-RAM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:44 ../monitor/hal/hal-utils.c:44
+msgid "Blank DVD-RAM Disc"
+msgstr "空白 DVD-RAM 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "DVD-RW Disc"
+msgstr "DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:46 ../monitor/hal/hal-utils.c:46
+msgid "Blank DVD-RW Disc"
+msgstr "空白 DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "DVD+R Disc"
+msgstr "DVD+R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:47 ../monitor/hal/hal-utils.c:47
+msgid "Blank DVD+R Disc"
+msgstr "空白 DVD+R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "DVD+RW Disc"
+msgstr "DVD+RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:48 ../monitor/hal/hal-utils.c:48
+msgid "Blank DVD+RW Disc"
+msgstr "空白 DVD+RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "DVD+R DL Disc"
+msgstr "DVD+R DL 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:49 ../monitor/hal/hal-utils.c:49
+msgid "Blank DVD+R DL Disc"
+msgstr "空白 DVD+R DL 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blu-Ray Disc"
+msgstr "Blu-Ray 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:50 ../monitor/hal/hal-utils.c:50
+msgid "Blank Blu-Ray Disc"
+msgstr "空白 Blu-Ray 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blu-Ray R Disc"
+msgstr "Blu-Ray R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:51 ../monitor/hal/hal-utils.c:51
+msgid "Blank Blu-Ray R Disc"
+msgstr "空白 Blu-Ray R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blu-Ray RW Disc"
+msgstr "Blu-Ray RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:52 ../monitor/hal/hal-utils.c:52
+msgid "Blank Blu-Ray RW Disc"
+msgstr "空白 Blu-Ray RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "HD DVD Disc"
+msgstr "HD DVD 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:53 ../monitor/hal/hal-utils.c:53
+msgid "Blank HD DVD Disc"
+msgstr "空白 HD DVD 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "HD DVD-R Disc"
+msgstr "HD DVD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:54 ../monitor/hal/hal-utils.c:54
+msgid "Blank HD DVD-R Disc"
+msgstr "空白 HD DVD-R 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "HD DVD-RW Disc"
+msgstr "HD DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:55 ../monitor/hal/hal-utils.c:55
+msgid "Blank HD DVD-RW Disc"
+msgstr "空白 HD DVD-RW 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "MO Disc"
+msgstr "MO 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:56 ../monitor/hal/hal-utils.c:56
+msgid "Blank MO Disc"
+msgstr "空白 MO 光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Disc"
+msgstr "光碟"
+
+#: ../monitor/gphoto2/hal-utils.c:57 ../monitor/hal/hal-utils.c:57
+msgid "Blank Disc"
+msgstr "空白光碟"
+
+#: ../monitor/hal/ghaldrive.c:130
+msgid "CD-ROM"
+msgstr "CD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:132
+msgid "CD-R"
+msgstr "CD-R"
+
+#: ../monitor/hal/ghaldrive.c:134
+msgid "CD-RW"
+msgstr "CD-RW"
+
+#: ../monitor/hal/ghaldrive.c:138
+msgid "DVD-ROM"
+msgstr "DVD-ROM"
+
+#: ../monitor/hal/ghaldrive.c:140
+msgid "DVD+R"
+msgstr "DVD+R"
+
+#: ../monitor/hal/ghaldrive.c:142
+msgid "DVD+RW"
+msgstr "DVD+RW"
+
+#: ../monitor/hal/ghaldrive.c:144
+msgid "DVD-R"
+msgstr "DVD-R"
+
+#: ../monitor/hal/ghaldrive.c:146
+msgid "DVD-RW"
+msgstr "DVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:148
+msgid "DVD-RAM"
+msgstr "DVD-RAM"
+
+#: ../monitor/hal/ghaldrive.c:151
+msgid "DVD±R"
+msgstr "DVD±R"
+
+#: ../monitor/hal/ghaldrive.c:154
+msgid "DVD±RW"
+msgstr "DVD±RW"
+
+#: ../monitor/hal/ghaldrive.c:156
+msgid "HDDVD"
+msgstr "HDDVD"
+
+#: ../monitor/hal/ghaldrive.c:158
+msgid "HDDVD-r"
+msgstr "HDDVD-r"
+
+#: ../monitor/hal/ghaldrive.c:160
+msgid "HDDVD-RW"
+msgstr "HDDVD-RW"
+
+#: ../monitor/hal/ghaldrive.c:162
+msgid "Blu-ray"
+msgstr "Blu-ray"
+
+#: ../monitor/hal/ghaldrive.c:164
+msgid "Blu-ray-R"
+msgstr "Blu-ray-R"
+
+#: ../monitor/hal/ghaldrive.c:166
+msgid "Blu-ray-RE"
+msgstr "Blu-ray-RE"
+
+#. translators: This wis something like "CD-ROM/DVD Drive" or
+#. "CD-RW/Blue-ray Drive" depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:172
+#, c-format
+msgid "%s/%s Drive"
+msgstr "%s/%s 光碟機"
+
+#. translators: This wis something like "CD-ROM Drive" or "CD-RW Drive
+#. depending on the properties of the drive
+#: ../monitor/hal/ghaldrive.c:178
+#, c-format
+msgid "%s Drive"
+msgstr "%s 光碟機"
+
+#: ../monitor/hal/ghaldrive.c:182
+msgid "Floppy Drive"
+msgstr "軟碟機"
+
+#: ../monitor/hal/ghaldrive.c:188
+msgid "Software RAID Drive"
+msgstr "軟體 RAID 陣列"
+
+#: ../monitor/hal/ghaldrive.c:190
+msgid "USB Drive"
+msgstr "USB 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:192
+msgid "ATA Drive"
+msgstr "ATA 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:194
+msgid "SCSI Drive"
+msgstr "SCSI 裝置"
+
+#: ../monitor/hal/ghaldrive.c:196
+msgid "FireWire Drive"
+msgstr "FireWire 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:200
+msgid "Tape Drive"
+msgstr "磁帶機"
+
+#: ../monitor/hal/ghaldrive.c:202
+msgid "CompactFlash Drive"
+msgstr "CompactFlash 裝置"
+
+#: ../monitor/hal/ghaldrive.c:204
+msgid "MemoryStick Drive"
+msgstr "MemoryStick 裝置"
+
+#: ../monitor/hal/ghaldrive.c:206
+msgid "SmartMedia Drive"
+msgstr "SmartMedia 裝置"
+
+#: ../monitor/hal/ghaldrive.c:208
+msgid "SD/MMC Drive"
+msgstr "SD/MMC 裝置"
+
+#: ../monitor/hal/ghaldrive.c:210
+msgid "Zip Drive"
+msgstr "Zip 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:212
+msgid "Jaz Drive"
+msgstr "Jaz 磁碟機"
+
+#: ../monitor/hal/ghaldrive.c:214
+msgid "Thumb Drive"
+msgstr "隨身碟"
+
+#: ../monitor/hal/ghaldrive.c:217
+msgid "Mass Storage Drive"
+msgstr "大量存放裝置"
+
+#: ../monitor/hal/ghaldrive.c:723
+#, c-format
+msgid "Failed to eject media; one or more volumes on the media are busy."
+msgstr "退出媒體失敗;該媒體上的一或多個儲存裝置正在忙碌。"
+
+#: ../monitor/hal/ghalmount.c:301 ../monitor/hal/ghalvolume.c:171
+#, c-format
+msgid "%.1f kB"
+msgstr "%.1f kB"
+
+#: ../monitor/hal/ghalmount.c:306 ../monitor/hal/ghalvolume.c:176
+#, c-format
+msgid "%.1f MB"
+msgstr "%.1f MB"
+
+#: ../monitor/hal/ghalmount.c:311 ../monitor/hal/ghalvolume.c:181
+#, c-format
+msgid "%.1f GB"
+msgstr "%.1f GB"
+
+#: ../monitor/hal/ghalmount.c:433 ../monitor/hal/ghalvolume.c:252
+msgid "Mixed Audio/Data Disc"
+msgstr "混合音樂/資料光碟"
+
+#. Translators: %s is the size of the mount (e.g. 512 MB)
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalmount.c:446 ../monitor/hal/ghalvolume.c:263
+#, c-format
+msgid "%s Media"
+msgstr "%s 媒體"
+
+#. Translators: %s is the size of the volume (e.g. 512 MB)
+#: ../monitor/hal/ghalvolume.c:240
+#, c-format
+msgid "%s Encrypted Data"
+msgstr "%s 加密的資料"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:57
+#, c-format
+msgid "%s: %s: error opening file: %s\n"
+msgstr "%s: %s:開啟檔案時發生錯誤:%s\n"
+
+#. Translators: the first %s is the program name, the
+#. second one is the URI of the file.
+#: ../programs/gvfs-cat.c:80
+#, c-format
+msgid "%s: %s, error writing to stdout"
+msgstr "%s: %s,錯誤寫入至 stdout"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:92
+#, c-format
+msgid "%s: %s: error reading: %s\n"
+msgstr "%s: %s:讀取檔案時發生錯誤:%s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-cat.c:110
+#, c-format
+msgid "%s: %s:error closing: %s\n"
+msgstr "%s: %s:發生錯誤時正關閉: %s\n"
+
+#: ../programs/gvfs-cat.c:136
+msgid "LOCATION... - concatenate LOCATIONS to standard output."
+msgstr "LOCATION... - 將 LOCATIONS 連接至標準輸出。"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-cat.c:141
+msgid ""
+"Concatenate files at locations and print to the standard output. Works just "
+"like the traditional cat utility, but using gvfs location instead local "
+"files: for example you can use something like smb://server/resource/file.txt "
+"as location to concatenate."
+msgstr ""
+"連接位置上的檔案並顯示到標準輸出。運作方式就像傳統的 cat 公用程式,只是使用 "
+"gvfs 位置代替 local 檔案:例如您可以使用像 smb://server/resource/file.txt 做"
+"為連接的位置。"
+
+#: ../programs/gvfs-cat.c:148
+msgid ""
+"Note: just pipe through cat if you need its formatting option like -n, -T or "
+"other."
+msgstr "注意:只要利用導管通過 cat 就可以使用它的格式選項如 -n, -T 或其他。"
+
+#. Translators: the %s is the program name. This error message
+#. means the user is calling gvfs-cat without any argument.
+#: ../programs/gvfs-cat.c:174 ../programs/gvfs-open.c:142
+#, c-format
+msgid "%s: missing locations"
+msgstr "%s:漏掉位置"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:56
+#, c-format
+msgid "%s: %s: error opening location: %s\n"
+msgstr "%s: %s:發生錯誤時正開啟位置: %s\n"
+
+#. Translators: the first %s is the program name, the second one
+#. is the URI of the file, the third is the error message.
+#: ../programs/gvfs-open.c:83
+#, c-format
+msgid "%s: %s: error launching application: %s\n"
+msgstr "%s: %s:執行應用程式時發生錯誤:%s\n"
+
+#: ../programs/gvfs-open.c:113
+msgid "FILES... - open FILES with registered application."
+msgstr "FILES... - 以註冊的應用程式開啟 FILES。"
+
+#. Translators: this message will appear after the usage string
+#. and before the list of options.
+#: ../programs/gvfs-open.c:117
+msgid ""
+"Opens the file(s) with the default application registered to handle the type "
+"of the file."
+msgstr "使用註冊為處理該檔案類型的預設應用程式來開啟檔案。"
+
+#~ msgid "dns-sd"
+#~ msgstr "dns-sd"
+
+#~ msgid "%s (in trash)"
+#~ msgstr "%s (於回收筒)"
+
+#~ msgid "Can't delete trash"
+#~ msgstr "無法刪除回收筒"
+
+#~ msgid "Trash directory notification not supported"
+#~ msgstr "不支援目錄通知"
+
+#~ msgid "Error creating port info list"
+#~ msgstr "建立通訊埠資訊清單時發生錯誤"
+
+#~ msgid "Error getting port info from port info list"
+#~ msgstr "從通訊埠資訊清單取得通訊埠資訊時發生錯誤"
+
+#~ msgid "File system is busy: %d open files"
+#~ msgstr "檔案系統忙碌中:開啟了 %d 個檔案"
+
+#~ msgid "Error listing folders"
+#~ msgstr "列出資料夾時發生錯誤"
+
+#~ msgid "Error listing files in folder"
+#~ msgstr "列出資料夾中的檔案時發生錯誤"
+
+#~ msgid "File unavailable"
+#~ msgstr "檔案無法使用"
+
+#~ msgid "%.1f kB Media"
+#~ msgstr "%.1f kB 媒體"
+
+#~ msgid "%.1f MB Media"
+#~ msgstr "%.1f MB 媒體"
+
+#~ msgid "%.1f GB Media"
+#~ msgstr "%.1f GB 媒體"
diff --git a/trunk/programs/Makefile.am b/trunk/programs/Makefile.am
new file mode 100644
index 00000000..7f7d9dc1
--- /dev/null
+++ b/trunk/programs/Makefile.am
@@ -0,0 +1,85 @@
+NULL =
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ $(GLIB_CFLAGS) \
+ -DGVFS_LOCALEDIR=\""$(localedir)"\" \
+ -DG_DISABLE_DEPRECATED
+
+libraries = \
+ $(GLIB_LIBS)
+
+bin_PROGRAMS = \
+ gvfs-mount \
+ gvfs-cat \
+ gvfs-open \
+ gvfs-save \
+ gvfs-ls \
+ gvfs-tree \
+ gvfs-info \
+ gvfs-trash \
+ gvfs-rename \
+ gvfs-rm \
+ gvfs-copy \
+ gvfs-move \
+ gvfs-monitor-file \
+ gvfs-monitor-dir \
+ gvfs-mkdir \
+ $(NULL)
+
+bin_SCRIPTS = \
+ gvfs-less \
+ $(NULL)
+
+if ENABLE_BASHCOMP
+profiledir = $(BASHCOMP_DIR)
+profile_SCRIPTS = gvfs-bash-completion.sh
+endif
+
+gvfs_cat_SOURCES = gvfs-cat.c
+gvfs_cat_LDADD = $(libraries)
+
+gvfs_open_SOURCES = gvfs-open.c
+gvfs_open_LDADD = $(libraries)
+
+gvfs_copy_SOURCES = gvfs-copy.c
+gvfs_copy_LDADD = $(libraries)
+
+gvfs_save_SOURCES = gvfs-save.c
+gvfs_save_LDADD = $(libraries)
+
+gvfs_info_SOURCES = gvfs-info.c
+gvfs_info_LDADD = $(libraries)
+
+gvfs_trash_SOURCES = gvfs-trash.c
+gvfs_trash_LDADD = $(libraries)
+
+gvfs_rename_SOURCES = gvfs-rename.c
+gvfs_rename_LDADD = $(libraries)
+
+gvfs_rm_SOURCES = gvfs-rm.c
+gvfs_rm_LDADD = $(libraries)
+
+gvfs_ls_SOURCES = gvfs-ls.c
+gvfs_ls_LDADD = $(libraries)
+
+gvfs_tree_SOURCES = gvfs-tree.c
+gvfs_tree_LDADD = $(libraries)
+
+gvfs_move_SOURCES = gvfs-move.c
+gvfs_move_LDADD = $(libraries)
+
+gvfs_mount_SOURCES = gvfs-mount.c
+gvfs_mount_LDADD = $(libraries)
+
+gvfs_monitor_dir_SOURCES = gvfs-monitor-dir.c
+gvfs_monitor_dir_LDADD = $(libraries)
+
+gvfs_monitor_file_SOURCES = gvfs-monitor-file.c
+gvfs_monitor_file_LDADD = $(libraries)
+
+gvfs_mkdir_SOURCES = gvfs-mkdir.c
+gvfs_mkdir_LDADD = $(libraries)
+
+EXTRA_DIST = gvfs-less gvfs-bash-completion.sh
diff --git a/trunk/programs/gvfs-bash-completion.sh b/trunk/programs/gvfs-bash-completion.sh
new file mode 100755
index 00000000..f5a3b9c9
--- /dev/null
+++ b/trunk/programs/gvfs-bash-completion.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2007 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+# USA.
+#
+# Author: David Zeuthen <davidz@redhat.com>
+
+# Check for bash
+[ -z "$BASH_VERSION" ] && return
+
+####################################################################################################
+
+
+__gvfs_multiple_uris() {
+ local IFS=$'\n'
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+
+ COMPREPLY=($(compgen -W '$(gvfs-ls --show-completions "$cur")' -- ""))
+
+ # don't misbehave on colons; See item E13 at http://tiswww.case.edu/php/chet/bash/FAQ
+ # We handle this locally be extracting any BLAH: prefix and removing it from the result.
+ # Not great, but better than globally changing COMP_WORDBREAKS
+
+ case "$cur" in
+ *:*)
+ case "$COMP_WORDBREAKS" in
+ *:*) colon_prefix=$(echo $cur | sed 's/:[^:]*$/:/' )
+ COMPREPLY=${COMPREPLY##${colon_prefix}}
+ ;;
+ esac
+ ;;
+ esac
+}
+
+####################################################################################################
+
+complete -o nospace -F __gvfs_multiple_uris gvfs-ls
+complete -o nospace -F __gvfs_multiple_uris gvfs-info
+complete -o nospace -F __gvfs_multiple_uris gvfs-cat
+complete -o nospace -F __gvfs_multiple_uris gvfs-less
+complete -o nospace -F __gvfs_multiple_uris gvfs-copy
+complete -o nospace -F __gvfs_multiple_uris gvfs-mkdir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-dir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-file
+complete -o nospace -F __gvfs_multiple_uris gvfs-move
+complete -o nospace -F __gvfs_multiple_uris gvfs-open
+complete -o nospace -F __gvfs_multiple_uris gvfs-rm
+complete -o nospace -F __gvfs_multiple_uris gvfs-save
+complete -o nospace -F __gvfs_multiple_uris gvfs-trash
+complete -o nospace -F __gvfs_multiple_uris gvfs-tree
diff --git a/trunk/programs/gvfs-cat.c b/trunk/programs/gvfs-cat.c
new file mode 100644
index 00000000..bd3969f2
--- /dev/null
+++ b/trunk/programs/gvfs-cat.c
@@ -0,0 +1,193 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static gchar **locations = NULL;
+
+static GOptionEntry entries[] = {
+ {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "locations", NULL},
+ {NULL}
+};
+
+static void
+cat (GFile * file)
+{
+ GInputStream *in;
+ char buffer[1024 * 8 + 1];
+ char *p;
+ gssize res;
+ gboolean close_res;
+ GError *error;
+
+ error = NULL;
+ in = (GInputStream *) g_file_read (file, NULL, &error);
+ if (in == NULL)
+ {
+ /* Translators: the first %s is the program name, the second one */
+ /* is the URI of the file, the third is the error message. */
+ g_printerr (_("%s: %s: error opening file: %s\n"),
+ g_get_prgname (), g_file_get_uri (file), error->message);
+ g_error_free (error);
+ return;
+ }
+
+ while (1)
+ {
+ res =
+ g_input_stream_read (in, buffer, sizeof (buffer) - 1, NULL, &error);
+ if (res > 0)
+ {
+ ssize_t written;
+
+ p = buffer;
+ while (res > 0)
+ {
+ written = write (STDOUT_FILENO, p, res);
+
+ if (written == -1 && errno != EINTR)
+ {
+ /* Translators: the first %s is the program name, the */
+ /* second one is the URI of the file. */
+ g_printerr (_("%s: %s, error writing to stdout"),
+ g_get_prgname (), g_file_get_uri (file));
+ goto out;
+ }
+ res -= written;
+ p += written;
+ }
+ }
+ else if (res < 0)
+ {
+ /* Translators: the first %s is the program name, the second one */
+ /* is the URI of the file, the third is the error message. */
+ g_printerr (_("%s: %s: error reading: %s\n"),
+ g_get_prgname (), g_file_get_uri (file),
+ error->message);
+ g_error_free (error);
+ error = NULL;
+ break;
+ }
+ else if (res == 0)
+ break;
+ }
+
+ out:
+
+ close_res = g_input_stream_close (in, NULL, &error);
+ if (!close_res)
+ {
+ /* Translators: the first %s is the program name, the second one */
+ /* is the URI of the file, the third is the error message. */
+ g_printerr (_("%s: %s:error closing: %s\n"),
+ g_get_prgname (), g_file_get_uri (file), error->message);
+ g_error_free (error);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error = NULL;
+ GOptionContext *context = NULL;
+ GFile *file;
+ gchar *summary;
+ int i;
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ g_type_init ();
+
+ /* Translators: this message will appear immediately after the */
+ /* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE> */
+ context =
+ g_option_context_new (_("LOCATION... - concatenate LOCATIONS "
+ "to standard output."));
+
+ /* Translators: this message will appear after the usage string */
+ /* and before the list of options. */
+ summary = g_strconcat (_("Concatenate files at locations and print to the "
+ "standard output. Works just like the traditional "
+ "cat utility, but using gvfs location instead "
+ "local files: for example you can use something "
+ "like smb://server/resource/file.txt as location "
+ "to concatenate."),
+ "\n\n",
+ _("Note: just pipe through cat if you need its "
+ "formatting option like -n, -T or other."), NULL);
+
+ g_option_context_set_summary (context, summary);
+
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+
+ g_option_context_free (context);
+ g_free (summary);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (!locations)
+ {
+ /* Translators: the %s is the program name. This error message */
+ /* means the user is calling gvfs-cat without any argument. */
+ g_printerr (_("%s: missing locations"), g_get_prgname ());
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ return 1;
+ }
+
+ i = 0;
+
+ do
+ {
+ file = g_file_new_for_commandline_arg (locations[i]);
+ cat (file);
+ g_object_unref (file);
+ }
+ while (locations[++i] != NULL);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-copy.c b/trunk/programs/gvfs-copy.c
new file mode 100644
index 00000000..ed960da4
--- /dev/null
+++ b/trunk/programs/gvfs-copy.c
@@ -0,0 +1,193 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static gboolean progress = FALSE;
+static gboolean interactive = FALSE;
+static gboolean no_dereference = FALSE;
+static gboolean backup = FALSE;
+static gboolean preserve = FALSE;
+static gboolean no_target_directory = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "no-target-directory", 'T', 0, G_OPTION_ARG_NONE, &no_target_directory, "no target directory", NULL },
+ { "progress", 'p', 0, G_OPTION_ARG_NONE, &progress, "show progress", NULL },
+ { "interactive", 'i', 0, G_OPTION_ARG_NONE, &interactive, "prompt before overwrite", NULL },
+ { "preserve", 'p', 0, G_OPTION_ARG_NONE, &preserve, "preserve all attributes", NULL },
+ { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, "backup existing destination files", NULL },
+ { "no-dereference", 'P', 0, G_OPTION_ARG_NONE, &no_dereference, "never follow symbolic links", NULL },
+ { NULL }
+};
+
+static gboolean
+is_dir (GFile *file)
+{
+ GFileInfo *info;
+ gboolean res;
+
+ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
+ res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ if (info)
+ g_object_unref (info);
+ return res;
+}
+
+static void
+show_progress (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ g_print ("progress %"G_GINT64_FORMAT"/%"G_GINT64_FORMAT"\n",
+ current_num_bytes, total_num_bytes);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *source, *dest, *target;
+ gboolean dest_is_dir;
+ char *basename;
+ int i;
+ GFileCopyFlags flags;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- output files at <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (argc <= 2)
+ {
+ g_printerr ("Missing operand\n");
+ return 1;
+ }
+
+ dest = g_file_new_for_commandline_arg (argv[argc-1]);
+
+ if (no_target_directory && argc > 3)
+ {
+ g_printerr ("Too many arguments\n");
+ g_object_unref (dest);
+ return 1;
+ }
+
+ dest_is_dir = is_dir (dest);
+
+ if (!dest_is_dir && argc > 3)
+ {
+ g_printerr ("Target %s is not a directory\n", argv[argc-1]);
+ g_object_unref (dest);
+ return 1;
+ }
+
+ for (i = 1; i < argc - 1; i++)
+ {
+ source = g_file_new_for_commandline_arg (argv[i]);
+
+ if (dest_is_dir && !no_target_directory)
+ {
+ basename = g_file_get_basename (source);
+ target = g_file_get_child (dest, basename);
+ g_free (basename);
+ }
+ else
+ target = g_object_ref (dest);
+
+ flags = 0;
+ if (backup)
+ flags |= G_FILE_COPY_BACKUP;
+ if (!interactive)
+ flags |= G_FILE_COPY_OVERWRITE;
+ if (no_dereference)
+ flags |= G_FILE_COPY_NOFOLLOW_SYMLINKS;
+ if (preserve)
+ flags |= G_FILE_COPY_ALL_METADATA;
+
+
+ error = NULL;
+ if (!g_file_copy (source, target, flags, NULL, progress?show_progress:NULL, NULL, &error))
+ {
+ if (interactive && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ char line[16];
+
+ g_error_free (error);
+ error = NULL;
+
+ basename = g_file_get_basename (target);
+ g_print ("overwrite %s?", basename);
+ g_free (basename);
+
+ if (fgets(line, sizeof (line), stdin) &&
+ line[0] == 'y')
+ {
+ flags |= G_FILE_COPY_OVERWRITE;
+ if (!g_file_copy (source, target, flags, NULL, NULL, NULL, &error))
+ goto copy_failed;
+ }
+ }
+ else
+ {
+ copy_failed:
+ g_printerr ("Error copying file %s: %s\n", argv[i], error->message);
+ g_error_free (error);
+ }
+ }
+
+ g_object_unref (source);
+ g_object_unref (target);
+ }
+
+ g_object_unref (dest);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-info.c b/trunk/programs/gvfs-info.c
new file mode 100644
index 00000000..b3d6e0e1
--- /dev/null
+++ b/trunk/programs/gvfs-info.c
@@ -0,0 +1,386 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static char *attributes = NULL;
+static gboolean nofollow_symlinks = FALSE;
+static gboolean filesystem = FALSE;
+static gboolean writable = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "query-writable", 'w', 0, G_OPTION_ARG_NONE, &writable, "List writable attributes", NULL },
+ { "filesystem", 'f', 0, G_OPTION_ARG_NONE, &filesystem, "Get filesystem info", NULL },
+ { "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, "The attributes to get", NULL },
+ { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, "Don't follow symlinks", NULL },
+ { NULL }
+};
+
+static const char *
+type_to_string (GFileType type)
+{
+ switch (type)
+ {
+ default:
+ return "invalid type";
+
+ case G_FILE_TYPE_UNKNOWN:
+ return "unknown";
+
+ case G_FILE_TYPE_REGULAR:
+ return "regular";
+
+ case G_FILE_TYPE_DIRECTORY:
+ return "directory";
+
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ return "symlink";
+
+ case G_FILE_TYPE_SPECIAL:
+ return "special";
+
+ case G_FILE_TYPE_SHORTCUT:
+ return "shortcut";
+
+ case G_FILE_TYPE_MOUNTABLE:
+ return "mountable";
+ }
+}
+
+static char *
+escape_string (const char *in)
+{
+ GString *str;
+ static char *hex_digits = "0123456789abcdef";
+ char c;
+
+
+ str = g_string_new ("");
+
+ while ((c = *in++) != 0)
+ {
+ if (c >= 32 && c <= 126 && c != '\\')
+ g_string_append_c (str, c);
+ else
+ {
+ g_string_append (str, "\\x");
+ g_string_append_c (str, hex_digits[(c >> 8) & 0xf]);
+ g_string_append_c (str, hex_digits[c & 0xf]);
+ }
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+show_attributes (GFileInfo *info)
+{
+ char **attributes;
+ char *s;
+ int i;
+
+ attributes = g_file_info_list_attributes (info, NULL);
+
+ g_print ("attributes:\n");
+ for (i = 0; attributes[i] != NULL; i++)
+ {
+ /* list the icons in order rather than displaying "GThemedIcon:0x8df7200" */
+ if (strcmp (attributes[i], "standard::icon") == 0)
+ {
+ GIcon *icon;
+ int j;
+ const char * const *names = NULL;
+ icon = g_file_info_get_icon (info);
+
+ /* only look up names if GThemedIcon */
+ if (G_IS_THEMED_ICON(icon))
+ {
+ names = g_themed_icon_get_names (G_THEMED_ICON (icon));
+ g_print (" %s: ", attributes[i]);
+ for (j = 0; names[j] != NULL; j++)
+ g_print ("%s%s", names[j], (names[j+1] == NULL)?"":", ");
+ g_print ("\n");
+ }
+ else
+ {
+ s = g_file_info_get_attribute_as_string (info, attributes[i]);
+ g_print (" %s: %s\n", attributes[i], s);
+ g_free (s);
+ }
+ }
+ else
+ {
+ s = g_file_info_get_attribute_as_string (info, attributes[i]);
+ g_print (" %s: %s\n", attributes[i], s);
+ g_free (s);
+ }
+ }
+ g_strfreev (attributes);
+}
+
+static void
+show_info (GFileInfo *info)
+{
+ const char *name, *type;
+ char *escaped;
+ goffset size;
+
+ name = g_file_info_get_display_name (info);
+ if (name)
+ g_print ("display name: %s\n", name);
+
+ name = g_file_info_get_edit_name (info);
+ if (name)
+ g_print ("edit name: %s\n", name);
+
+ name = g_file_info_get_name (info);
+ if (name)
+ {
+ escaped = escape_string (name);
+ g_print ("name: %s\n", escaped);
+ g_free (escaped);
+ }
+
+ type = type_to_string (g_file_info_get_file_type (info));
+ g_print ("type: %s\n", type);
+
+ size = g_file_info_get_size (info);
+ g_print ("size: %"G_GUINT64_FORMAT"\n", (guint64)size);
+
+ if (g_file_info_get_is_hidden (info))
+ g_print ("hidden\n");
+
+ show_attributes (info);
+}
+
+static void
+query_info (GFile *file)
+{
+ GFileQueryInfoFlags flags;
+ GFileInfo *info;
+ GError *error;
+
+ if (file == NULL)
+ return;
+
+ if (attributes == NULL)
+ attributes = "*";
+
+ flags = 0;
+ if (nofollow_symlinks)
+ flags |= G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS;
+
+ error = NULL;
+ if (filesystem)
+ info = g_file_query_filesystem_info (file, attributes, NULL, &error);
+ else
+ info = g_file_query_info (file, attributes, flags, NULL, &error);
+
+ if (info == NULL)
+ {
+ g_printerr ("Error getting info: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (filesystem)
+ show_attributes (info);
+ else
+ show_info (info);
+
+ g_object_unref (info);
+}
+
+static char *
+attribute_type_to_string (GFileAttributeType type)
+{
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_INVALID:
+ return "invalid";
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ return "string";
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ return "bytestring";
+ case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
+ return "boolean";
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ return "uint32";
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ return "int32";
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ return "uint64";
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ return "int64";
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ return "object";
+ default:
+ return "uknown type";
+ }
+}
+
+static char *
+attribute_flags_to_string (GFileAttributeInfoFlags flags)
+{
+ GString *s;
+ int i;
+ gboolean first;
+ struct {
+ guint32 mask;
+ char *descr;
+ } flag_descr[] = {
+ {
+ G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE,
+ "Copy with file"
+ },
+ {
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED,
+ "Keep with file when moved"
+ }
+ };
+
+ first = TRUE;
+
+ s = g_string_new ("");
+ for (i = 0; i < G_N_ELEMENTS (flag_descr); i++)
+ {
+ if (flags & flag_descr[i].mask)
+ {
+ if (!first)
+ g_string_append (s, ", ");
+ g_string_append (s, flag_descr[i].descr);
+ first = FALSE;
+ }
+ }
+
+ return g_string_free (s, FALSE);
+}
+
+static void
+get_writable_info (GFile *file)
+{
+ GFileAttributeInfoList *list;
+ GError *error;
+ int i;
+ char *flags;
+
+ if (file == NULL)
+ return;
+
+ error = NULL;
+
+ list = g_file_query_settable_attributes (file, NULL, &error);
+ if (list == NULL)
+ {
+ g_printerr ("Error getting writable attributes: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_print ("Settable attributes:\n");
+ for (i = 0; i < list->n_infos; i++)
+ {
+ flags = attribute_flags_to_string (list->infos[i].flags);
+ g_print (" %s (%s%s%s)\n",
+ list->infos[i].name,
+ attribute_type_to_string (list->infos[i].type),
+ (*flags != 0)?", ":"", flags);
+ g_free (flags);
+ }
+
+ g_file_attribute_info_list_unref (list);
+
+ list = g_file_query_writable_namespaces (file, NULL, &error);
+ if (list == NULL)
+ {
+ g_printerr ("Error getting writable namespaces: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (list->n_infos > 0)
+ {
+ g_print ("Writable attribute namespaces:\n");
+ for (i = 0; i < list->n_infos; i++)
+ {
+ flags = attribute_flags_to_string (list->infos[i].flags);
+ g_print (" %s (%s%s%s)\n",
+ list->infos[i].name,
+ attribute_type_to_string (list->infos[i].type),
+ (*flags != 0)?", ":"", flags);
+ }
+ }
+
+ g_file_attribute_info_list_unref (list);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- show info for <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ if (writable)
+ get_writable_info (file);
+ else
+ query_info (file);
+ g_object_unref (file);
+ }
+ }
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-less b/trunk/programs/gvfs-less
new file mode 100755
index 00000000..ba0c6768
--- /dev/null
+++ b/trunk/programs/gvfs-less
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2007 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+# USA.
+#
+# Author: David Zeuthen <davidz@redhat.com>
+
+LESSOPEN="|gvfs-cat %s"; export LESSOPEN
+exec less "$@"
diff --git a/trunk/programs/gvfs-ls.c b/trunk/programs/gvfs-ls.c
new file mode 100644
index 00000000..ecc136d3
--- /dev/null
+++ b/trunk/programs/gvfs-ls.c
@@ -0,0 +1,437 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static char *attributes = NULL;
+static gboolean show_hidden = FALSE;
+static gboolean show_long = FALSE;
+static char *show_completions = NULL;
+
+static GOptionEntry entries[] =
+{
+ { "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, "The attributes to get", NULL },
+ { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, "Show hidden files", NULL },
+ { "long", 'l', 0, G_OPTION_ARG_NONE, &show_long, "Use a long listing format", NULL },
+ { "show-completions", 'c', 0, G_OPTION_ARG_STRING, &show_completions, "Show completions", NULL},
+ { NULL }
+};
+
+static const char *
+type_to_string (GFileType type)
+{
+ switch (type)
+ {
+ default:
+ return "invalid type";
+
+ case G_FILE_TYPE_UNKNOWN:
+ return "unknown";
+
+ case G_FILE_TYPE_REGULAR:
+ return "regular";
+
+ case G_FILE_TYPE_DIRECTORY:
+ return "directory";
+
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ return "symlink";
+
+ case G_FILE_TYPE_SPECIAL:
+ return "special";
+
+ case G_FILE_TYPE_SHORTCUT:
+ return "shortcut";
+
+ case G_FILE_TYPE_MOUNTABLE:
+ return "mountable";
+ }
+}
+
+static void
+show_info (GFileInfo *info)
+{
+ const char *name, *type;
+ goffset size;
+ char **attributes;
+ int i;
+ gboolean first_attr;
+
+ if ((g_file_info_get_is_hidden (info)) && !show_hidden)
+ return;
+
+ name = g_file_info_get_name (info);
+ if (name == NULL)
+ name = "";
+
+ size = g_file_info_get_size (info);
+ type = type_to_string (g_file_info_get_file_type (info));
+ if (show_long)
+ g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", name, (guint64)size, type);
+ else
+ g_print ("%s", name);
+
+ first_attr = TRUE;
+ attributes = g_file_info_list_attributes (info, NULL);
+ for (i = 0 ; attributes[i] != NULL; i++)
+ {
+ char *val_as_string;
+
+ if (!show_long ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_SIZE) == 0 ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0 ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) == 0)
+ continue;
+
+ if (first_attr)
+ {
+ g_print ("\t");
+ first_attr = FALSE;
+ }
+ else
+ g_print (" ");
+ val_as_string = g_file_info_get_attribute_as_string (info, attributes[i]);
+ g_print ("%s=%s", attributes[i], val_as_string);
+ g_free (val_as_string);
+ }
+
+ g_strfreev (attributes);
+
+ g_print ("\n");
+}
+
+static void
+list (GFile *file)
+{
+ GFileEnumerator *enumerator;
+ GFileInfo *info;
+ GError *error;
+
+ if (file == NULL)
+ return;
+
+ error = NULL;
+ enumerator = g_file_enumerate_children (file, attributes, 0, NULL, &error);
+ if (enumerator == NULL)
+ {
+ g_printerr ("Error: %s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ return;
+ }
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
+ {
+ show_info (info);
+
+ g_object_unref (info);
+ }
+
+ if (error)
+ {
+ g_printerr ("Error: %s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
+ if (!g_file_enumerator_close (enumerator, NULL, &error))
+ {
+ g_printerr ("Error closing enumerator: %s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+}
+
+static void
+print_mounts (const char *prefix)
+{
+ GList *l;
+ GList *mounts;
+ GVolumeMonitor *volume_monitor;
+
+ volume_monitor = g_volume_monitor_get ();
+
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ if (mounts != NULL)
+ {
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = l->data;
+ GFile *mount_root;
+ char *uri;
+
+ mount_root = g_mount_get_root (mount);
+ uri = g_file_get_uri (mount_root);
+ if (prefix == NULL ||
+ g_str_has_prefix (uri, prefix))
+ g_print ("%s\n", uri);
+ g_free (uri);
+ g_object_unref (mount_root);
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+ }
+ g_object_unref (volume_monitor);
+
+ if (prefix == NULL || g_str_has_prefix ("file:///", prefix))
+ g_print ("file:///\n");
+}
+
+static char*
+shell_quote (const gchar *unquoted_string)
+{
+ const gchar *p;
+ GString *dest;
+
+ dest = g_string_new ("");
+
+ p = unquoted_string;
+
+ while (*p)
+ {
+ if (*p == ' ')
+ g_string_append (dest, "\\ ");
+ else if (*p == '\n')
+ g_string_append (dest, "^J");
+ else if (*p == '\\')
+ g_string_append (dest, "\\\\");
+ else if (*p == '\'')
+ g_string_append (dest, "\\'");
+ else if (*p == '"')
+ g_string_append (dest, "\\\"");
+ else
+ g_string_append_c (dest, *p);
+
+ ++p;
+ }
+
+ return g_string_free (dest, FALSE);
+}
+
+static void
+show_completed_file (GFile *hit,
+ gboolean is_dir,
+ const char *arg)
+{
+ char *path, *cwd, *display, *t;
+ GFile *cwd_f;
+ GFile *home;
+
+ if (g_file_is_native (hit))
+ {
+ cwd = g_get_current_dir ();
+ cwd_f = g_file_new_for_path (cwd);
+ g_free (cwd);
+
+ home = g_file_new_for_path (g_get_home_dir ());
+
+ if ((g_file_has_prefix (hit, home) ||
+ g_file_equal (hit, home)) &&
+ arg[0] == '~')
+ {
+ t = g_file_get_relative_path (home, hit);
+ path = g_strconcat ("~", (t != NULL) ? "/": "", t, NULL);
+ g_free (t);
+ }
+ else if (g_file_has_prefix (hit, cwd_f) &&
+ !g_path_is_absolute (arg))
+ path = g_file_get_relative_path (cwd_f, hit);
+ else
+ path = g_file_get_path (hit);
+
+ g_object_unref (cwd_f);
+ g_object_unref (home);
+
+ display = shell_quote (path);
+ g_free (path);
+ }
+ else
+ display = g_file_get_uri (hit);
+
+ g_print ("%s%s\n", display, (is_dir)?"/":"");
+ g_free (display);
+}
+
+static void
+print_completions (const char *arg)
+{
+ GFile *f;
+ GFile *parent;
+ char *basename;
+ char *unescaped, *t;
+
+ unescaped = g_shell_unquote (arg, NULL);
+ if (unescaped == NULL)
+ unescaped = g_strdup (arg);
+
+ if (*unescaped == '~')
+ {
+ t = unescaped;
+ unescaped = g_strconcat (g_get_home_dir(), t+1, NULL);
+ g_free (t);
+ }
+
+ f = g_file_new_for_commandline_arg (unescaped);
+
+ if (g_str_has_suffix (arg, "/") || *arg == 0)
+ {
+ parent = g_object_ref (f);
+ basename = g_strdup ("");
+ }
+ else
+ {
+ parent = g_file_get_parent (f);
+ basename = g_file_get_basename (f);
+ }
+
+ if (parent == NULL ||
+ strchr (arg, '/') == NULL ||
+ !g_file_query_exists (parent, NULL))
+ {
+ GMount *mount;
+ mount = g_file_find_enclosing_mount (f, NULL, NULL);
+ if (mount == NULL)
+ print_mounts (unescaped);
+ else
+ g_object_unref (mount);
+ }
+
+ if (parent != NULL)
+ {
+ GFileEnumerator *enumerator;
+ enumerator = g_file_enumerate_children (parent,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ 0,
+ NULL,
+ NULL);
+ if (enumerator != NULL)
+ {
+ GFileInfo *info;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ const char *name;
+ GFileType type;
+
+ name = g_file_info_get_name (info);
+ type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+ if (name != NULL && g_str_has_prefix (name, basename))
+ {
+ GFile *entry;
+
+ entry = g_file_get_child (parent, name);
+ show_completed_file (entry, type == G_FILE_TYPE_DIRECTORY, arg);
+ g_object_unref (entry);
+ }
+ g_object_unref (info);
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+ }
+ g_object_unref (parent);
+ }
+
+ g_object_unref (f);
+ g_free (basename);
+ g_free (unescaped);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- list files at <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (attributes != NULL)
+ {
+ /* asking for attributes implies -l; otherwise it won't get shown */
+ show_long = TRUE;
+ }
+
+ attributes = g_strconcat (G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
+ attributes != NULL ? "," : "",
+ attributes,
+ NULL);
+
+ if (show_completions != NULL)
+ {
+ print_completions (show_completions);
+ return 0;
+ }
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ list (file);
+ g_object_unref (file);
+ }
+ }
+ else
+ {
+ char *cwd;
+
+ cwd = g_get_current_dir ();
+ file = g_file_new_for_path (cwd);
+ g_free (cwd);
+ list (file);
+ g_object_unref (file);
+ }
+
+ g_free (attributes);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-mkdir.c b/trunk/programs/gvfs-mkdir.c
new file mode 100644
index 00000000..483ebd87
--- /dev/null
+++ b/trunk/programs/gvfs-mkdir.c
@@ -0,0 +1,95 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <locale.h>
+#include <gio/gio.h>
+
+static gboolean parent = FALSE;
+static GOptionEntry entries[] =
+{
+ { "parent", 'p', 0, G_OPTION_ARG_NONE, &parent, "create parent directories", NULL },
+ { NULL }
+};
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- delete files");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ error = NULL;
+ if (parent)
+ {
+ if (!g_file_make_directory_with_parents (file, NULL, &error))
+ {
+ g_print ("Error creating directory: %s\n", error->message);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ if (!g_file_make_directory (file, NULL, &error))
+ {
+ g_print ("Error creating directory: %s\n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-monitor-dir.c b/trunk/programs/gvfs-monitor-dir.c
new file mode 100644
index 00000000..bf2f6288
--- /dev/null
+++ b/trunk/programs/gvfs-monitor-dir.c
@@ -0,0 +1,116 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+static GMainLoop *main_loop;
+
+static GOptionEntry entries[] = {
+ { NULL }
+};
+
+static gboolean
+dir_monitor_callback (GFileMonitor* monitor,
+ GFile* child,
+ GFile* other_file,
+ GFileMonitorEvent eflags)
+{
+
+ char *name = g_file_get_parse_name (child);
+
+ g_print ("Directory Monitor Event:\n");
+ g_print ("Child = %s\n", name);
+ g_free (name);
+
+ switch (eflags)
+ {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ g_print ("Event = CHANGED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ g_print ("Event = CHANGES_DONE_HINT\n");
+ break;
+ case G_FILE_MONITOR_EVENT_DELETED:
+ g_print ("Event = DELETED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_CREATED:
+ g_print ("Event = CREATED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
+ g_print ("Event = PRE_UNMOUNT\n");
+ break;
+ case G_FILE_MONITOR_EVENT_UNMOUNTED:
+ g_print ("Event = UNMOUNTED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ g_print ("Event = ATTRIB CHANGED\n");
+ break;
+ }
+
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GFileMonitor* dmonitor;
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- monitor directory <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc > 1)
+ {
+ file = g_file_new_for_commandline_arg (argv[1]);
+ dmonitor = g_file_monitor_directory (file, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
+ if (dmonitor != NULL)
+ g_signal_connect (dmonitor, "changed", (GCallback)dir_monitor_callback, NULL);
+ else
+ {
+ g_print ("Monitoring not supported for %s\n", argv[1]);
+ return 1;
+ }
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-monitor-file.c b/trunk/programs/gvfs-monitor-file.c
new file mode 100644
index 00000000..842ed938
--- /dev/null
+++ b/trunk/programs/gvfs-monitor-file.c
@@ -0,0 +1,105 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+static GMainLoop *main_loop;
+
+static GOptionEntry entries[] = {
+ { NULL }
+};
+
+static gboolean
+file_monitor_callback (GFileMonitor* monitor,
+ GFile* child,
+ GFile* other_file,
+ GFileMonitorEvent eflags)
+{
+ g_print ("File Monitor Event:\n");
+ g_print ("File = %s\n", g_file_get_parse_name (child));
+ switch (eflags)
+ {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ g_print ("Event = CHANGED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ g_print ("Event = CHANGES_DONE_HINT\n");
+ break;
+ case G_FILE_MONITOR_EVENT_DELETED:
+ g_print ("Event = DELETED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_CREATED:
+ g_print ("Event = CREATED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_UNMOUNTED:
+ g_print ("Event = UNMOUNTED\n");
+ break;
+ case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
+ g_print ("Event = PRE_UNMOUNT\n");
+ break;
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ g_print ("Event = ATTRIB CHANGED\n");
+ break;
+ }
+
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GFileMonitor* fmonitor;
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- monitor file <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc > 1)
+ {
+ file = g_file_new_for_commandline_arg (argv[1]);
+ fmonitor = g_file_monitor_file (file, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
+ g_signal_connect (fmonitor, "changed", (GCallback)file_monitor_callback, NULL);
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-mount.c b/trunk/programs/gvfs-mount.c
new file mode 100644
index 00000000..70936c98
--- /dev/null
+++ b/trunk/programs/gvfs-mount.c
@@ -0,0 +1,951 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <gio/gio.h>
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#define STDIN_FILENO 0
+
+static int outstanding_mounts = 0;
+static GMainLoop *main_loop;
+
+
+static gboolean mount_mountable = FALSE;
+static gboolean mount_unmount = FALSE;
+static gboolean mount_list = FALSE;
+static gboolean extra_detail = FALSE;
+static gboolean mount_monitor = FALSE;
+static const char *unmount_scheme = NULL;
+static const char *mount_device_file = NULL;
+
+static const GOptionEntry entries[] =
+{
+ { "mountable", 'm', 0, G_OPTION_ARG_NONE, &mount_mountable, "Mount as mountable", NULL },
+ { "device", 'd', 0, G_OPTION_ARG_STRING, &mount_device_file, "Mount volume with device file", NULL},
+ { "unmount", 'u', 0, G_OPTION_ARG_NONE, &mount_unmount, "Unmount", NULL},
+ { "unmount-scheme", 's', 0, G_OPTION_ARG_STRING, &unmount_scheme, "Unmount all mounts with the given scheme", NULL},
+ { "list", 'l', 0, G_OPTION_ARG_NONE, &mount_list, "List", NULL},
+ { "detail", 'i', 0, G_OPTION_ARG_NONE, &extra_detail, "Show extra information for List and Monitor", NULL},
+ { "monitor", 'o', 0, G_OPTION_ARG_NONE, &mount_monitor, "Monitor events", NULL},
+ { NULL }
+};
+
+static char *
+prompt_for (const char *prompt, const char *default_value, gboolean echo)
+{
+#ifdef HAVE_TERMIOS_H
+ struct termios term_attr;
+ int old_flags;
+ gboolean restore_flags;
+#endif
+ char data[256];
+ int len;
+
+ if (default_value && *default_value != 0)
+ g_print ("%s [%s]: ", prompt, default_value);
+ else
+ g_print ("%s: ", prompt);
+
+ data[0] = 0;
+
+#ifdef HAVE_TERMIOS_H
+ restore_flags = FALSE;
+ if (!echo && tcgetattr (STDIN_FILENO, &term_attr) == 0)
+ {
+ old_flags = term_attr.c_lflag;
+ term_attr.c_lflag &= ~ECHO;
+ restore_flags = TRUE;
+
+ if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr) != 0)
+ g_print ("Warning! Password will be echoed");
+ }
+
+#endif
+
+ fgets(data, sizeof (data), stdin);
+
+#ifdef HAVE_TERMIOS_H
+ if (restore_flags)
+ {
+ term_attr.c_lflag = old_flags;
+ tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_attr);
+ }
+#endif
+
+ len = strlen (data);
+ if (len > 0 && data[len-1] == '\n')
+ data[len-1] = 0;
+
+ if (!echo)
+ g_print ("\n");
+
+ if (*data == 0 && default_value)
+ return g_strdup (default_value);
+ return g_strdup (data);
+}
+
+static void
+ask_password_cb (GMountOperation *op,
+ const char *message,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags)
+{
+ char *s;
+ g_print ("%s\n", message);
+
+ if (flags & G_ASK_PASSWORD_NEED_USERNAME)
+ {
+ s = prompt_for ("User", default_user, TRUE);
+ g_mount_operation_set_username (op, s);
+ g_free (s);
+ }
+
+ if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
+ {
+ s = prompt_for ("Domain", default_domain, TRUE);
+ g_mount_operation_set_domain (op, s);
+ g_free (s);
+ }
+
+ if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
+ {
+ s = prompt_for ("Password", NULL, FALSE);
+ g_mount_operation_set_password (op, s);
+ g_free (s);
+ }
+
+ g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
+}
+
+static void
+mount_mountable_done_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GFile *target;
+ GError *error = NULL;
+
+ target = g_file_mount_mountable_finish (G_FILE (object), res, &error);
+
+ if (target == NULL)
+ g_print ("Error mounting location: %s\n", error->message);
+ else
+ g_object_unref (target);
+
+ outstanding_mounts--;
+
+ if (outstanding_mounts == 0)
+ g_main_loop_quit (main_loop);
+}
+
+static void
+mount_done_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ gboolean succeeded;
+ GError *error = NULL;
+
+ succeeded = g_file_mount_enclosing_volume_finish (G_FILE (object), res, &error);
+
+ if (!succeeded)
+ g_print ("Error mounting location: %s\n", error->message);
+
+ outstanding_mounts--;
+
+ if (outstanding_mounts == 0)
+ g_main_loop_quit (main_loop);
+}
+
+static GMountOperation *
+new_mount_op (void)
+{
+ GMountOperation *op;
+
+ op = g_mount_operation_new ();
+
+ g_signal_connect (op, "ask_password", G_CALLBACK (ask_password_cb), NULL);
+
+ /* TODO: we *should* also connect to the "aborted" signal but since we the
+ * main thread is blocked handling input we won't get that signal
+ * anyway...
+ */
+
+ return op;
+}
+
+
+static void
+mount (GFile *file)
+{
+ GMountOperation *op;
+
+ if (file == NULL)
+ return;
+
+ op = new_mount_op ();
+
+ if (mount_mountable)
+ g_file_mount_mountable (file, 0, op, NULL, mount_mountable_done_cb, op);
+ else
+ g_file_mount_enclosing_volume (file, 0, op, NULL, mount_done_cb, op);
+
+ outstanding_mounts++;
+}
+
+static void
+unmount_done_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ gboolean succeeded;
+ GError *error = NULL;
+
+ succeeded = g_mount_unmount_finish (G_MOUNT (object), res, &error);
+
+ g_object_unref (G_MOUNT (object));
+
+ if (!succeeded)
+ g_print ("Error unmounting mount: %s\n", error->message);
+
+ outstanding_mounts--;
+
+ if (outstanding_mounts == 0)
+ g_main_loop_quit (main_loop);
+}
+
+static void
+unmount (GFile *file)
+{
+ GMount *mount;
+ GError *error = NULL;
+
+ if (file == NULL)
+ return;
+
+ mount = g_file_find_enclosing_mount (file, NULL, &error);
+ if (mount == NULL)
+ {
+ g_print ("Error finding enclosing mount: %s\n", error->message);
+ return;
+ }
+
+ g_mount_unmount (mount, 0, NULL, unmount_done_cb, NULL);
+
+ outstanding_mounts++;
+}
+
+/* =============== list mounts ================== */
+
+static gboolean
+iterate_gmain_timeout_function (gpointer data)
+{
+ g_main_loop_quit (main_loop);
+ return FALSE;
+}
+
+static void
+iterate_gmain(void)
+{
+ g_timeout_add (500, iterate_gmain_timeout_function, NULL);
+ g_main_loop_run (main_loop);
+}
+
+static void
+show_themed_icon_names (GThemedIcon *icon, int indent)
+{
+ char **names;
+ char **iter;
+
+ g_print ("%*sthemed icons:", indent, " ");
+
+ names = NULL;
+
+ g_object_get (icon, "names", &names, NULL);
+
+ for (iter = names; *iter; iter++)
+ g_print (" [%s]", *iter);
+
+ g_print ("\n");
+ g_strfreev (names);
+}
+
+/* don't copy-paste this code */
+static char *
+get_type_name (gpointer object)
+{
+ const char *type_name;
+ char *ret;
+
+ type_name = g_type_name (G_TYPE_FROM_INSTANCE (object));
+ if (strcmp ("GProxyDrive", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-drive-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyVolume", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-volume-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyMount", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-mount-volume-monitor-name"));
+ }
+ else if (strcmp ("GProxyShadowMount", type_name) == 0)
+ {
+ ret = g_strdup_printf ("%s (%s)",
+ type_name,
+ (const char *) g_object_get_data (G_OBJECT (object),
+ "g-proxy-shadow-mount-volume-monitor-name"));
+ }
+ else
+ {
+ ret = g_strdup (type_name);
+ }
+
+ return ret;
+}
+
+static void
+list_mounts (GList *mounts,
+ int indent,
+ gboolean only_with_no_volume)
+{
+ GList *l;
+ int c;
+ GMount *mount;
+ GVolume *volume;
+ char *name, *uuid, *uri;
+ GFile *root;
+ GIcon *icon;
+ char **x_content_types;
+ char *type_name;
+
+ for (c = 0, l = mounts; l != NULL; l = l->next, c++)
+ {
+ mount = (GMount *) l->data;
+
+ if (only_with_no_volume)
+ {
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL)
+ {
+ g_object_unref (volume);
+ continue;
+ }
+ }
+
+ name = g_mount_get_name (mount);
+ root = g_mount_get_root (mount);
+ uri = g_file_get_uri (root);
+
+ g_print ("%*sMount(%d): %s -> %s\n", indent, "", c, name, uri);
+
+ type_name = get_type_name (mount);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
+
+ if (extra_detail)
+ {
+ uuid = g_mount_get_uuid (mount);
+ if (uuid)
+ g_print ("%*suuid=%s\n", indent + 2, "", uuid);
+
+ icon = g_mount_get_icon (mount);
+ if (icon)
+ {
+ if (G_IS_THEMED_ICON (icon))
+ show_themed_icon_names (G_THEMED_ICON (icon), indent + 2);
+
+ g_object_unref (icon);
+ }
+
+ x_content_types = g_mount_guess_content_type_sync (mount, FALSE, NULL, NULL);
+ if (x_content_types != NULL && g_strv_length (x_content_types) > 0)
+ {
+ int n;
+ g_print ("%*sx_content_types:", indent + 2, "");
+ for (n = 0; x_content_types[n] != NULL; n++)
+ g_print (" %s", x_content_types[n]);
+ g_print ("\n");
+ }
+ g_strfreev (x_content_types);
+
+ g_print ("%*scan_unmount=%d\n", indent + 2, "", g_mount_can_unmount (mount));
+ g_print ("%*scan_eject=%d\n", indent + 2, "", g_mount_can_eject (mount));
+ g_print ("%*sis_shadowed=%d\n", indent + 2, "", g_mount_is_shadowed (mount));
+ g_free (uuid);
+ }
+
+ g_object_unref (root);
+ g_free (name);
+ g_free (uri);
+ }
+}
+
+static void
+list_volumes (GList *volumes,
+ int indent,
+ gboolean only_with_no_drive)
+{
+ GList *l, *mounts;
+ int c, i;
+ GMount *mount;
+ GVolume *volume;
+ GDrive *drive;
+ char *name;
+ char *uuid;
+ GFile *activation_root;
+ char **ids;
+ GIcon *icon;
+ char *type_name;
+
+ for (c = 0, l = volumes; l != NULL; l = l->next, c++)
+ {
+ volume = (GVolume *) l->data;
+
+ if (only_with_no_drive)
+ {
+ drive = g_volume_get_drive (volume);
+ if (drive != NULL)
+ {
+ g_object_unref (drive);
+ continue;
+ }
+ }
+
+ name = g_volume_get_name (volume);
+
+ g_print ("%*sVolume(%d): %s\n", indent, "", c, name);
+ g_free (name);
+
+ type_name = get_type_name (volume);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
+
+ if (extra_detail)
+ {
+ ids = g_volume_enumerate_identifiers (volume);
+ if (ids && ids[0] != NULL)
+ {
+ g_print ("%*sids:\n", indent+2, "");
+ for (i = 0; ids[i] != NULL; i++)
+ {
+ char *id = g_volume_get_identifier (volume,
+ ids[i]);
+ g_print ("%*s %s: '%s'\n", indent+2, "", ids[i], id);
+ g_free (id);
+ }
+ }
+ g_strfreev (ids);
+
+ uuid = g_volume_get_uuid (volume);
+ if (uuid)
+ g_print ("%*suuid=%s\n", indent + 2, "", uuid);
+ activation_root = g_volume_get_activation_root (volume);
+ if (activation_root)
+ {
+ char *uri;
+ uri = g_file_get_uri (activation_root);
+ g_print ("%*sactivation_root=%s\n", indent + 2, "", uri);
+ g_free (uri);
+ g_object_unref (activation_root);
+ }
+ icon = g_volume_get_icon (volume);
+ if (icon)
+ {
+ if (G_IS_THEMED_ICON (icon))
+ show_themed_icon_names (G_THEMED_ICON (icon), indent + 2);
+
+ g_object_unref (icon);
+ }
+
+ g_print ("%*scan_mount=%d\n", indent + 2, "", g_volume_can_mount (volume));
+ g_print ("%*scan_eject=%d\n", indent + 2, "", g_volume_can_eject (volume));
+ g_free (uuid);
+ }
+
+ mount = g_volume_get_mount (volume);
+ if (mount)
+ {
+ mounts = g_list_prepend (NULL, mount);
+ list_mounts (mounts, indent + 2, FALSE);
+ g_list_free (mounts);
+ g_object_unref (mount);
+ }
+ }
+}
+
+static void
+list_drives (GList *drives,
+ int indent)
+{
+ GList *volumes, *l;
+ int c, i;
+ GDrive *drive;
+ char *name;
+ char **ids;
+ GIcon *icon;
+ char *type_name;
+
+ for (c = 0, l = drives; l != NULL; l = l->next, c++)
+ {
+ drive = (GDrive *) l->data;
+ name = g_drive_get_name (drive);
+
+ g_print ("%*sDrive(%d): %s\n", indent, "", c, name);
+ g_free (name);
+
+ type_name = get_type_name (drive);
+ g_print ("%*sType: %s\n", indent+2, "", type_name);
+ g_free (type_name);
+
+ if (extra_detail)
+ {
+ ids = g_drive_enumerate_identifiers (drive);
+ if (ids && ids[0] != NULL)
+ {
+ g_print ("%*sids:\n", indent+2, "");
+ for (i = 0; ids[i] != NULL; i++)
+ {
+ char *id = g_drive_get_identifier (drive,
+ ids[i]);
+ g_print ("%*s %s: '%s'\n", indent+2, "", ids[i], id);
+ g_free (id);
+ }
+ }
+ g_strfreev (ids);
+
+ icon = g_drive_get_icon (drive);
+ if (icon)
+ {
+ if (G_IS_THEMED_ICON (icon))
+ show_themed_icon_names (G_THEMED_ICON (icon), indent + 2);
+ g_object_unref (icon);
+ }
+
+ g_print ("%*sis_media_removable=%d\n", indent + 2, "", g_drive_is_media_removable (drive));
+ g_print ("%*shas_media=%d\n", indent + 2, "", g_drive_has_media (drive));
+ g_print ("%*sis_media_check_automatic=%d\n", indent + 2, "", g_drive_is_media_check_automatic (drive));
+ g_print ("%*scan_poll_for_media=%d\n", indent + 2, "", g_drive_can_poll_for_media (drive));
+ g_print ("%*scan_eject=%d\n", indent + 2, "", g_drive_can_eject (drive));
+ }
+
+ volumes = g_drive_get_volumes (drive);
+ list_volumes (volumes, indent + 2, FALSE);
+ g_list_foreach (volumes, (GFunc)g_object_unref, NULL);
+ g_list_free (volumes);
+ }
+}
+
+
+static void
+list_monitor_items(void)
+{
+ GVolumeMonitor *volume_monitor;
+ GList *drives, *volumes, *mounts;
+
+ volume_monitor = g_volume_monitor_get();
+
+ /* populate gvfs network mounts */
+ iterate_gmain();
+
+ drives = g_volume_monitor_get_connected_drives (volume_monitor);
+ list_drives (drives, 0);
+ g_list_foreach (drives, (GFunc)g_object_unref, NULL);
+ g_list_free (drives);
+
+ volumes = g_volume_monitor_get_volumes (volume_monitor);
+ list_volumes (volumes, 0, TRUE);
+ g_list_foreach (volumes, (GFunc)g_object_unref, NULL);
+ g_list_free (volumes);
+
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ list_mounts (mounts, 0, TRUE);
+ g_list_foreach (mounts, (GFunc)g_object_unref, NULL);
+ g_list_free (mounts);
+
+ g_object_unref (volume_monitor);
+}
+
+static void
+unmount_all_with_scheme (const char *scheme)
+{
+ GVolumeMonitor *volume_monitor;
+ GList *mounts;
+ GList *l;
+
+ volume_monitor = g_volume_monitor_get();
+
+ /* populate gvfs network mounts */
+ iterate_gmain();
+
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ for (l = mounts; l != NULL; l = l->next) {
+ GMount *mount = G_MOUNT (l->data);
+ GFile *root;
+
+ root = g_mount_get_root (mount);
+ if (g_file_has_uri_scheme (root, scheme)) {
+ unmount (root);
+ }
+ g_object_unref (root);
+ }
+ g_list_foreach (mounts, (GFunc)g_object_unref, NULL);
+ g_list_free (mounts);
+
+ g_object_unref (volume_monitor);
+}
+
+static void
+mount_with_device_file_cb (GObject *object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVolume *volume;
+ gboolean succeeded;
+ GError *error = NULL;
+
+ volume = G_VOLUME (object);
+
+ succeeded = g_volume_mount_finish (volume, res, &error);
+
+ if (!succeeded)
+ {
+ g_print ("Error mounting %s: %s\n",
+ g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE),
+ error->message);
+ }
+ else
+ {
+ GMount *mount;
+ GFile *root;
+ char *mount_path;
+
+ mount = g_volume_get_mount (volume);
+ root = g_mount_get_root (mount);
+ mount_path = g_file_get_path (root);
+
+ g_print ("Mounted %s at %s\n",
+ g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE),
+ mount_path);
+
+ g_object_unref (mount);
+ g_object_unref (root);
+ g_free (mount_path);
+ }
+
+ outstanding_mounts--;
+
+ if (outstanding_mounts == 0)
+ g_main_loop_quit (main_loop);
+}
+
+static void
+mount_with_device_file (const char *device_file)
+{
+ GVolumeMonitor *volume_monitor;
+ GList *volumes;
+ GList *l;
+
+ volume_monitor = g_volume_monitor_get();
+
+ volumes = g_volume_monitor_get_volumes (volume_monitor);
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ GVolume *volume = G_VOLUME (l->data);
+
+ if (g_strcmp0 (g_volume_get_identifier (volume,
+ G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE), device_file) == 0)
+ {
+ GMountOperation *op;
+
+ op = new_mount_op ();
+
+ g_volume_mount (volume,
+ G_MOUNT_MOUNT_NONE,
+ op,
+ NULL,
+ mount_with_device_file_cb,
+ op);
+
+ outstanding_mounts++;
+ }
+ }
+ g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
+ g_list_free (volumes);
+
+ if (outstanding_mounts == 0)
+ {
+ g_print ("No volume for device file %s\n", device_file);
+ return;
+ }
+
+ g_object_unref (volume_monitor);
+}
+
+static void
+monitor_print_mount (GMount *mount)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, mount);
+ list_mounts (l, 2, FALSE);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_print_volume (GVolume *volume)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, volume);
+ list_volumes (l, 2, FALSE);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_print_drive (GDrive *drive)
+{
+ if (extra_detail)
+ {
+ GList *l;
+ l = g_list_prepend (NULL, drive);
+ list_drives (l, 2);
+ g_list_free (l);
+ g_print ("\n");
+ }
+}
+
+static void
+monitor_mount_added (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount added: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_removed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount removed: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_changed (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_mount_pre_unmount (GVolumeMonitor *volume_monitor, GMount *mount)
+{
+ char *name;
+ name = g_mount_get_name (mount);
+ g_print ("Mount pre-unmount: '%s'\n", name);
+ g_free (name);
+ monitor_print_mount (mount);
+}
+
+static void
+monitor_volume_added (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume added: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_removed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume removed: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_volume_changed (GVolumeMonitor *volume_monitor, GVolume *volume)
+{
+ char *name;
+ name = g_volume_get_name (volume);
+ g_print ("Volume changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_volume (volume);
+}
+
+static void
+monitor_drive_connected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive connected: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_disconnected (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive disconnected: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_changed (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive changed: '%s'\n", name);
+ g_free (name);
+ monitor_print_drive (drive);
+}
+
+static void
+monitor_drive_eject_button (GVolumeMonitor *volume_monitor, GDrive *drive)
+{
+ char *name;
+ name = g_drive_get_name (drive);
+ g_print ("Drive eject button: '%s'\n", name);
+ g_free (name);
+}
+
+static void
+monitor (void)
+{
+ GMainLoop *loop;
+ GVolumeMonitor *volume_monitor;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ volume_monitor = g_volume_monitor_get ();
+
+ g_signal_connect (volume_monitor, "mount-added", (GCallback) monitor_mount_added, NULL);
+ g_signal_connect (volume_monitor, "mount-removed", (GCallback) monitor_mount_removed, NULL);
+ g_signal_connect (volume_monitor, "mount-changed", (GCallback) monitor_mount_changed, NULL);
+ g_signal_connect (volume_monitor, "mount-pre-unmount", (GCallback) monitor_mount_pre_unmount, NULL);
+ g_signal_connect (volume_monitor, "volume-added", (GCallback) monitor_volume_added, NULL);
+ g_signal_connect (volume_monitor, "volume-removed", (GCallback) monitor_volume_removed, NULL);
+ g_signal_connect (volume_monitor, "volume-changed", (GCallback) monitor_volume_changed, NULL);
+ g_signal_connect (volume_monitor, "drive-connected", (GCallback) monitor_drive_connected, NULL);
+ g_signal_connect (volume_monitor, "drive-disconnected", (GCallback) monitor_drive_disconnected, NULL);
+ g_signal_connect (volume_monitor, "drive-changed", (GCallback) monitor_drive_changed, NULL);
+ g_signal_connect (volume_monitor, "drive-eject-button", (GCallback) monitor_drive_eject_button, NULL);
+
+ g_print ("Monitoring events. Press Ctrl+C to quit.\n");
+
+ g_main_loop_run (main_loop);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- mount <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ if (mount_list)
+ list_monitor_items ();
+ else if (mount_device_file != NULL)
+ {
+ mount_with_device_file (mount_device_file);
+ }
+ else if (unmount_scheme != NULL)
+ {
+ unmount_all_with_scheme (unmount_scheme);
+ }
+ else if (mount_monitor)
+ {
+ monitor ();
+ }
+ else if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ if (mount_unmount)
+ unmount (file);
+ else
+ mount (file);
+ g_object_unref (file);
+ }
+ }
+
+ if (outstanding_mounts > 0)
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-move.c b/trunk/programs/gvfs-move.c
new file mode 100644
index 00000000..7fab61ca
--- /dev/null
+++ b/trunk/programs/gvfs-move.c
@@ -0,0 +1,184 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static gboolean progress = FALSE;
+static gboolean interactive = FALSE;
+static gboolean backup = FALSE;
+static gboolean no_target_directory = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "no-target-directory", 'T', 0, G_OPTION_ARG_NONE, &no_target_directory, "no target directory", NULL },
+ { "progress", 'p', 0, G_OPTION_ARG_NONE, &progress, "show progress", NULL },
+ { "interactive", 'i', 0, G_OPTION_ARG_NONE, &interactive, "prompt before overwrite", NULL },
+ { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, "backup existing destination files", NULL },
+ { NULL }
+};
+
+static gboolean
+is_dir (GFile *file)
+{
+ GFileInfo *info;
+ gboolean res;
+
+ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
+ res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ if (info)
+ g_object_unref (info);
+ return res;
+}
+
+static void
+show_progress (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ g_print ("progress %"G_GINT64_FORMAT"/%"G_GINT64_FORMAT"\n",
+ current_num_bytes, total_num_bytes);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *source, *dest, *target;
+ gboolean dest_is_dir;
+ char *basename;
+ int i;
+ GFileCopyFlags flags;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- output files at <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (argc <= 2)
+ {
+ g_printerr ("Missing operand\n");
+ return 1;
+ }
+
+ dest = g_file_new_for_commandline_arg (argv[argc-1]);
+
+ if (no_target_directory && argc > 3)
+ {
+ g_printerr ("Too many arguments\n");
+ g_object_unref (dest);
+ return 1;
+ }
+
+ dest_is_dir = is_dir (dest);
+
+ if (!dest_is_dir && argc > 3)
+ {
+ g_printerr ("Target %s is not a directory\n", argv[argc-1]);
+ g_object_unref (dest);
+ return 1;
+ }
+
+ for (i = 1; i < argc - 1; i++)
+ {
+ source = g_file_new_for_commandline_arg (argv[i]);
+
+ if (dest_is_dir && !no_target_directory)
+ {
+ basename = g_file_get_basename (source);
+ target = g_file_get_child (dest, basename);
+ g_free (basename);
+ }
+ else
+ target = g_object_ref (dest);
+
+ flags = 0;
+ if (backup)
+ flags |= G_FILE_COPY_BACKUP;
+ if (!interactive)
+ flags |= G_FILE_COPY_OVERWRITE;
+
+ error = NULL;
+ if (!g_file_move (source, target, flags, NULL, progress?show_progress:NULL, NULL, &error))
+ {
+ if (interactive && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ char line[16];
+
+ g_error_free (error);
+ error = NULL;
+
+ basename = g_file_get_basename (target);
+ g_print ("overwrite %s?", basename);
+ g_free (basename);
+
+ if (fgets(line, sizeof (line), stdin) &&
+ line[0] == 'y')
+ {
+ flags |= G_FILE_COPY_OVERWRITE;
+ if (!g_file_move (source, target, flags, NULL, NULL, NULL, &error))
+ goto move_failed;
+ }
+ }
+ else
+ {
+ move_failed:
+ g_printerr ("Error moving file %s: %s\n", argv[i], error->message);
+ g_error_free (error);
+ }
+ }
+
+ g_object_unref (source);
+ g_object_unref (target);
+ }
+
+ g_object_unref (dest);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-open.c b/trunk/programs/gvfs-open.c
new file mode 100644
index 00000000..1f734b8c
--- /dev/null
+++ b/trunk/programs/gvfs-open.c
@@ -0,0 +1,170 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static gchar **locations = NULL;
+
+static GOptionEntry entries[] = {
+ {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "files", NULL},
+ {NULL}
+};
+
+static gboolean
+is_file_uri_with_anchor (char *str)
+{
+ if (g_ascii_strncasecmp (str, "file:", 5) == 0 &&
+ strchr (str, '#') != NULL)
+ return TRUE;
+ return FALSE;
+}
+
+static void
+open (GFile *file, char *arg_string)
+{
+ GAppInfo *app;
+ GError *error;
+ GList l = {NULL};
+ gboolean res;
+
+ error = NULL;
+ app = g_file_query_default_handler (file, NULL, &error);
+
+ if (app == NULL)
+ {
+ /* Translators: the first %s is the program name, the second one */
+ /* is the URI of the file, the third is the error message. */
+ g_printerr (_("%s: %s: error opening location: %s\n"),
+ g_get_prgname (), g_file_get_uri (file), error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (g_file_is_native (file) && !is_file_uri_with_anchor (arg_string))
+ {
+ /* For normal files, pass in the canonicalized GFile as path */
+ l.data = file;
+ res = g_app_info_launch (app, &l,
+ NULL, &error);
+ }
+ else
+ {
+ /* However, for uris, use the original string, as it might be
+ modified by passing throught GFile (e.g. mailto: links)
+ */
+ l.data = arg_string;
+ res = g_app_info_launch_uris (app, &l,
+ NULL, &error);
+ }
+
+ if (!res)
+ {
+ /* Translators: the first %s is the program name, the second one */
+ /* is the URI of the file, the third is the error message. */
+ g_printerr (_("%s: %s: error launching application: %s\n"),
+ g_get_prgname (), g_file_get_uri (file), error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (app);
+
+ return;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error = NULL;
+ GOptionContext *context = NULL;
+ GFile *file;
+ gchar *summary;
+ int i;
+
+ setlocale (LC_ALL, "");
+
+ bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ g_type_init ();
+
+ /* Translators: this message will appear immediately after the */
+ /* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE> */
+ context =
+ g_option_context_new (_("FILES... - open FILES with registered application."));
+
+ /* Translators: this message will appear after the usage string */
+ /* and before the list of options. */
+ summary = _("Opens the file(s) with the default application "
+ "registered to handle the type of the file.");
+
+ g_option_context_set_summary (context, summary);
+
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (!locations)
+ {
+ /* Translators: the %s is the program name. This error message */
+ /* means the user is calling gvfs-cat without any argument. */
+ g_printerr (_("%s: missing locations"), g_get_prgname ());
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ return 1;
+ }
+
+ i = 0;
+
+ do
+ {
+ file = g_file_new_for_commandline_arg (locations[i]);
+ open (file, locations[i]);
+ g_object_unref (file);
+ }
+ while (locations[++i] != NULL);
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-rename.c b/trunk/programs/gvfs-rename.c
new file mode 100644
index 00000000..cb2a0638
--- /dev/null
+++ b/trunk/programs/gvfs-rename.c
@@ -0,0 +1,80 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Christian Kellner <gicmo@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <gio/gio.h>
+
+static GOptionEntry entries[] =
+{
+ { NULL }
+};
+
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error;
+ GFile *file;
+ GFile *new_file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- rename file");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc < 3)
+ {
+ g_printerr ("Usage: %s location new_name\n",
+ g_get_prgname ());
+ return 1;
+ }
+
+ file = g_file_new_for_commandline_arg (argv[1]);
+
+ new_file = g_file_set_display_name (file, argv[2],
+ NULL, &error);
+
+ if (new_file == NULL)
+ {
+ g_print ("Error: %s\n", error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ char *uri = g_file_get_uri (new_file);
+ g_print ("Rename successful. New uri: %s\n", uri);
+ g_object_unref (new_file);
+ g_free (uri);
+ }
+
+ g_object_unref (file);
+ return 0;
+}
diff --git a/trunk/programs/gvfs-rm.c b/trunk/programs/gvfs-rm.c
new file mode 100644
index 00000000..cb666549
--- /dev/null
+++ b/trunk/programs/gvfs-rm.c
@@ -0,0 +1,69 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <gio/gio.h>
+
+static GOptionEntry entries[] =
+{
+ { NULL }
+};
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- delete files");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ error = NULL;
+ if (!g_file_delete (file, NULL, &error))
+ {
+ g_print ("Error deleting file: %s\n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ }
+ }
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-save.c b/trunk/programs/gvfs-save.c
new file mode 100644
index 00000000..ffe21bad
--- /dev/null
+++ b/trunk/programs/gvfs-save.c
@@ -0,0 +1,184 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static char *etag = NULL;
+static gboolean backup = FALSE;
+static gboolean create = FALSE;
+static gboolean append = FALSE;
+static gboolean priv = FALSE;
+static gboolean print_etag = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, "Create backup", NULL },
+ { "create", 'c', 0, G_OPTION_ARG_NONE, &create, "Only create if not existing", NULL },
+ { "append", 'a', 0, G_OPTION_ARG_NONE, &append, "Append to end of file", NULL },
+ { "private", 'p', 0, G_OPTION_ARG_NONE, &priv, "When creating a file, restrict access to the current user only", NULL },
+ { "print_etag", 'v', 0, G_OPTION_ARG_NONE, &print_etag, "Print new etag at end", NULL },
+ { "etag", 'e', 0, G_OPTION_ARG_STRING, &etag, "The etag of the file being overwritten", NULL },
+ { NULL }
+};
+
+static gboolean
+save (GFile *file)
+{
+ GOutputStream *out;
+ GFileCreateFlags flags;
+ char buffer[1025];
+ char *p;
+ gssize res;
+ gboolean close_res;
+ GError *error;
+ gboolean save_res;
+
+ error = NULL;
+
+ flags = priv ? G_FILE_CREATE_PRIVATE : G_FILE_CREATE_NONE;
+
+ if (create)
+ out = (GOutputStream *)g_file_create (file, flags, NULL, &error);
+ else if (append)
+ out = (GOutputStream *)g_file_append_to (file, flags, NULL, &error);
+ else
+ out = (GOutputStream *)g_file_replace (file, etag, backup, flags, NULL, &error);
+ if (out == NULL)
+ {
+ g_printerr ("Error opening file: %s\n", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ save_res = TRUE;
+
+ while (1)
+ {
+ res = read (STDIN_FILENO, buffer, 1024);
+ if (res > 0)
+ {
+ ssize_t written;
+
+ p = buffer;
+ while (res > 0)
+ {
+ error = NULL;
+ written = g_output_stream_write (out, p, res, NULL, &error);
+ if (written == -1)
+ {
+ save_res = FALSE;
+ g_printerr ("Error writing to stream: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ res -= written;
+ p += written;
+ }
+ }
+ else if (res < 0)
+ {
+ save_res = FALSE;
+ perror ("Error reading stdin");
+ break;
+ }
+ else if (res == 0)
+ break;
+ }
+
+ out:
+
+ close_res = g_output_stream_close (out, NULL, &error);
+ if (!close_res)
+ {
+ save_res = FALSE;
+ g_printerr ("Error closing: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ if (close_res && print_etag)
+ {
+ char *etag;
+ etag = g_file_output_stream_get_etag (G_FILE_OUTPUT_STREAM (out));
+
+ if (etag)
+ g_print ("Etag: %s\n", etag);
+ else
+ g_print ("Etag not available\n");
+ g_free (etag);
+ }
+
+ g_object_unref (out);
+
+ return save_res;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+ gboolean res;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- output files at <location>");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ res = FALSE;
+
+ if (argc > 1)
+ {
+ file = g_file_new_for_commandline_arg (argv[1]);
+ res = save (file);
+ g_object_unref (file);
+ }
+
+ if (res)
+ return 0;
+ return 1;
+}
diff --git a/trunk/programs/gvfs-trash.c b/trunk/programs/gvfs-trash.c
new file mode 100644
index 00000000..7fa1aecd
--- /dev/null
+++ b/trunk/programs/gvfs-trash.c
@@ -0,0 +1,70 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <gio/gio.h>
+
+
+static GOptionEntry entries[] =
+{
+ { NULL }
+};
+
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- move files to trash");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ error = NULL;
+ if (!g_file_trash (file, NULL, &error))
+ {
+ g_print ("Error trashing file: %s\n", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+ }
+ }
+
+ return 0;
+}
diff --git a/trunk/programs/gvfs-tree.c b/trunk/programs/gvfs-tree.c
new file mode 100644
index 00000000..a9ff3b06
--- /dev/null
+++ b/trunk/programs/gvfs-tree.c
@@ -0,0 +1,280 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <locale.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+static gboolean show_hidden = FALSE;
+static gboolean follow_symlinks = FALSE;
+
+static GOptionEntry entries[] =
+{
+ { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, "Show hidden files", NULL },
+ { "follow-symlinks", 'l', 0, G_OPTION_ARG_NONE, &follow_symlinks, "Follow symlinks, mounts and shortcuts like dirs", NULL },
+};
+
+static gint
+sort_info_by_name (GFileInfo *a, GFileInfo *b)
+{
+ const char *na;
+ const char *nb;
+
+ na = g_file_info_get_name (a);
+ nb = g_file_info_get_name (b);
+
+ if (na == NULL)
+ na = "";
+ if (nb == NULL)
+ nb = "";
+
+ return strcmp (na, nb);
+}
+
+static void
+do_tree (GFile *f, int level, guint64 pattern)
+{
+ GFileEnumerator *enumerator;
+ GError *error = NULL;
+ unsigned int n;
+ GFileInfo *info;
+
+ info = g_file_query_info (f,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ 0,
+ NULL, NULL);
+ if (info != NULL)
+ {
+ if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_MOUNTABLE)
+ {
+ /* don't process mountables; we avoid these by getting the target_uri below */
+ g_object_unref (info);
+ return;
+ }
+ g_object_unref (info);
+ }
+
+ enumerator = g_file_enumerate_children (f,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
+ G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+ 0,
+ NULL,
+ &error);
+ if (enumerator != NULL)
+ {
+ GList *l;
+ GList *info_list;
+
+ info_list = NULL;
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ if (g_file_info_get_is_hidden (info) && !show_hidden)
+ {
+ g_object_unref (info);
+ }
+ else
+ {
+ info_list = g_list_prepend (info_list, info);
+ }
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+
+ info_list = g_list_sort (info_list, (GCompareFunc) sort_info_by_name);
+
+ for (l = info_list; l != NULL; l = l->next)
+ {
+ const char *name;
+ const char *target_uri;
+ GFileType type;
+ gboolean is_last_item;
+
+ info = l->data;
+ is_last_item = (l->next == NULL);
+
+ name = g_file_info_get_name (info);
+ type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+ if (name != NULL)
+ {
+
+ for (n = 0; n < level; n++)
+ {
+ if (pattern & (1<<n))
+ {
+ g_print ("| ");
+ }
+ else
+ {
+ g_print (" ");
+ }
+ }
+
+ if (is_last_item)
+ {
+ g_print ("`-- %s", name);
+ }
+ else
+ {
+ g_print ("|-- %s", name);
+ }
+
+ target_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
+ if (target_uri != NULL)
+ {
+ g_print (" -> %s", target_uri);
+ }
+ else
+ {
+ if (g_file_info_get_is_symlink (info))
+ {
+ const char *target;
+ target = g_file_info_get_symlink_target (info);
+ g_print (" -> %s", target);
+ }
+ }
+
+ g_print ("\n");
+
+ if ((type & G_FILE_TYPE_DIRECTORY) &&
+ (follow_symlinks || !g_file_info_get_is_symlink (info)))
+ {
+ guint64 new_pattern;
+ GFile *child;
+
+ if (is_last_item)
+ new_pattern = pattern;
+ else
+ new_pattern = pattern | (1<<level);
+
+ child = NULL;
+ if (target_uri != NULL)
+ {
+ if (follow_symlinks)
+ child = g_file_new_for_uri (target_uri);
+ }
+ else
+ {
+ child = g_file_get_child (f, name);
+ }
+
+ if (child != NULL)
+ {
+ do_tree (child, level + 1, new_pattern);
+ g_object_unref (child);
+ }
+ }
+ }
+ g_object_unref (info);
+ }
+ g_list_free (info_list);
+ }
+ else
+ {
+ for (n = 0; n < level; n++)
+ {
+ if (pattern & (1<<n))
+ {
+ g_print ("| ");
+ }
+ else
+ {
+ g_print (" ");
+ }
+ }
+
+ g_print (" [%s]\n", error->message);
+
+ g_error_free (error);
+ }
+}
+
+static void
+tree (GFile *f)
+{
+ char *uri;
+
+ uri = g_file_get_uri (f);
+ g_print ("%s\n", uri);
+ g_free (uri);
+
+ do_tree (f, 0, 0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error;
+ GOptionContext *context;
+ GFile *file;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ error = NULL;
+ context = g_option_context_new ("- list contents of directories in a tree-like format");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_free (context);
+
+ if (error != NULL)
+ {
+ g_printerr ("Error parsing commandline options: %s\n", error->message);
+ g_printerr ("\n");
+ g_printerr (_("Try \"%s --help\" for more information."),
+ g_get_prgname ());
+ g_printerr ("\n");
+ g_error_free(error);
+ return 1;
+ }
+
+ if (argc > 1)
+ {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ file = g_file_new_for_commandline_arg (argv[i]);
+ tree (file);
+ g_object_unref (file);
+ }
+ }
+ else
+ {
+ char *cwd;
+
+ cwd = g_get_current_dir ();
+ file = g_file_new_for_path (cwd);
+ g_free (cwd);
+ tree (file);
+ g_object_unref (file);
+ }
+
+ return 0;
+}
diff --git a/trunk/test/Makefile.am b/trunk/test/Makefile.am
new file mode 100644
index 00000000..70c0cb7a
--- /dev/null
+++ b/trunk/test/Makefile.am
@@ -0,0 +1,20 @@
+NULL =
+
+AM_CFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ $(GLIB_CFLAGS) \
+ -DG_DISABLE_DEPRECATED
+
+AM_LDFLAGS = \
+ $(GLIB_LIBS)
+
+noinst_PROGRAMS = \
+ test-query-info-stream \
+ benchmark-gvfs-small-files \
+ benchmark-gvfs-big-files \
+ benchmark-posix-small-files \
+ benchmark-posix-big-files \
+ $(NULL)
+
+EXTRA_DIST = benchmark-common.c
diff --git a/trunk/test/benchmark-common.c b/trunk/test/benchmark-common.c
new file mode 100644
index 00000000..8f7e9ccc
--- /dev/null
+++ b/trunk/test/benchmark-common.c
@@ -0,0 +1,217 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+/* This file should be included directly in each benchmark program */
+
+#define __USE_GNU 1
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <glib/gprintf.h>
+
+static GMainLoop *main_loop;
+
+typedef struct
+{
+ gdouble x;
+ gdouble y;
+}
+BenchmarkDataPoint;
+
+typedef struct
+{
+ /* Array of BenchmarkDataPoints */
+ GArray *points;
+}
+BenchmarkDataSet;
+
+typedef struct
+{
+ gchar *name;
+ gchar *x_unit;
+ gchar *y_unit;
+
+ GList *data_sets;
+}
+BenchmarkDataPlot;
+
+static gint benchmark_run (gint argc, gchar *argv []);
+
+GList *benchmark_data_plots = NULL;
+gboolean benchmark_is_running = FALSE;
+
+#if 0
+static void
+benchmark_begin_data_plot (const gchar *name, const gchar *x_unit, const gchar *y_unit)
+{
+ BenchmarkDataPlot *data_plot;
+
+ data_plot = g_new0 (BenchmarkDataPlot, 1);
+
+ data_plot->name = g_strdup (name);
+ data_plot->x_unit = g_strdup (x_unit);
+ data_plot->y_unit = g_strdup (y_unit);
+
+ data_plot->data_sets = NULL;
+
+ benchmark_data_plots = g_list_prepend (benchmark_data_plots, data_plot);
+}
+
+static void
+benchmark_begin_data_set (void)
+{
+ BenchmarkDataPlot *data_plot;
+ BenchmarkDataSet *data_set;
+
+ if (!benchmark_data_plots)
+ g_error ("Must begin a data plot before adding data sets!");
+
+ data_plot = benchmark_data_plots->data;
+
+ data_set = g_new0 (BenchmarkDataSet, 1);
+ data_set->points = g_array_new (FALSE, FALSE, sizeof (BenchmarkDataPoint));
+
+ data_plot->data_sets = g_list_prepend (data_plot->data_sets, data_set);
+}
+
+static void
+benchmark_add_data_point (gdouble x, gdouble y)
+{
+ BenchmarkDataPlot *data_plot;
+ BenchmarkDataSet *data_set;
+ BenchmarkDataPoint data_point;
+
+ if (!benchmark_data_plots)
+ g_error ("Must begin a data plot before adding data sets!");
+
+ data_plot = benchmark_data_plots->data;
+
+ if (!data_plot->data_sets)
+ g_error ("Must begin a data set before adding data points!");
+
+ data_set = data_plot->data_sets->data;
+
+ data_point.x = x;
+ data_point.y = y;
+
+ g_array_append_val (data_set->points, data_point);
+}
+
+#endif
+
+static void
+benchmark_end (void)
+{
+ BenchmarkDataPlot *plot;
+ GList *l;
+
+ /* Dump plots */
+
+ if (!benchmark_data_plots)
+ exit (1);
+
+ plot = benchmark_data_plots->data;
+ if (!plot)
+ exit (1);
+
+ for (l = plot->data_sets; l; l = g_list_next (l))
+ {
+ BenchmarkDataSet *set = l->data;
+ guint i;
+
+ for (i = 0; i < set->points->len; i++)
+ {
+ BenchmarkDataPoint *point = &g_array_index (set->points, BenchmarkDataPoint, i);
+
+ g_print ("%20lf %20lf\n", point->x, point->y);
+ }
+ }
+
+ exit (0);
+}
+
+static void
+benchmark_begin (const gchar *name)
+{
+ g_type_init ();
+ g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR);
+ main_loop = g_main_loop_new (NULL, FALSE);
+}
+
+G_GNUC_UNUSED static void
+benchmark_run_main_loop (void)
+{
+ g_main_loop_run (main_loop);
+}
+
+G_GNUC_UNUSED static void
+benchmark_quit_main_loop (void)
+{
+ g_main_loop_quit (main_loop);
+}
+
+static void
+benchmark_timeout (int signal)
+{
+ benchmark_is_running = FALSE;
+}
+
+G_GNUC_UNUSED static void
+benchmark_start_wallclock_timer (gint n_seconds)
+{
+ benchmark_is_running = TRUE;
+ signal (SIGALRM, benchmark_timeout);
+ alarm (n_seconds);
+}
+
+G_GNUC_UNUSED static void
+benchmark_start_cpu_timer (gint n_seconds)
+{
+ struct itimerval itv;
+
+ benchmark_is_running = TRUE;
+
+ memset (&itv, 0, sizeof (itv));
+ itv.it_value.tv_sec = n_seconds;
+
+ signal (SIGPROF, benchmark_timeout);
+ setitimer (ITIMER_PROF, &itv, NULL);
+}
+
+gint
+main (gint argc, gchar *argv [])
+{
+ gint result;
+
+ benchmark_begin (BENCHMARK_UNIT_NAME);
+ result = benchmark_run (argc, argv);
+ benchmark_end ();
+
+ return result;
+}
diff --git a/trunk/test/benchmark-gvfs-big-files.c b/trunk/test/benchmark-gvfs-big-files.c
new file mode 100644
index 00000000..af9c7b77
--- /dev/null
+++ b/trunk/test/benchmark-gvfs-big-files.c
@@ -0,0 +1,191 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define BENCHMARK_UNIT_NAME "gvfs-big-file"
+
+#include "benchmark-common.c"
+
+#define FILE_SIZE (1024 * 1024 * 50) /* 50 MiB */
+#define BUFFER_SIZE 4096
+#define ITERATIONS_NUM 1
+
+static gboolean
+is_dir (GFile *file)
+{
+ GFileInfo *info;
+ gboolean res;
+
+ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
+ res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ if (info)
+ g_object_unref (info);
+ return res;
+}
+
+static GFile *
+create_file (GFile *base_dir)
+{
+ GFile *scratch_file;
+ gchar *scratch_name;
+ GOutputStream *output_stream;
+ gint pid;
+ GError *error = NULL;
+ gchar buffer [BUFFER_SIZE];
+ gint i;
+
+ pid = getpid ();
+ scratch_name = g_strdup_printf ("gvfs-benchmark-scratch-%d", pid);
+ scratch_file = g_file_resolve_relative_path (base_dir, scratch_name);
+ g_free (scratch_name);
+
+ if (!scratch_file)
+ return NULL;
+
+ output_stream = G_OUTPUT_STREAM (g_file_replace (scratch_file, 0, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+ if (!output_stream)
+ {
+ g_printerr ("Failed to create scratch file: %s\n", error->message);
+ g_object_unref (scratch_file);
+ return NULL;
+ }
+
+ memset (buffer, 0xaa, BUFFER_SIZE);
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ if (g_output_stream_write (output_stream, buffer, BUFFER_SIZE, NULL, &error) < BUFFER_SIZE)
+ {
+ g_printerr ("Failed to populate scratch file: %s\n", error->message);
+ g_output_stream_close (output_stream, NULL, NULL);
+ g_object_unref (output_stream);
+ g_object_unref (scratch_file);
+ return NULL;
+ }
+ }
+
+ g_output_stream_close (output_stream, NULL, NULL);
+ g_object_unref (output_stream);
+ return scratch_file;
+}
+
+static void
+read_file (GFile *scratch_file)
+{
+ GInputStream *input_stream;
+ GError *error = NULL;
+ gint i;
+
+ input_stream = (GInputStream *) g_file_read (scratch_file, NULL, &error);
+ if (!input_stream)
+ {
+ g_printerr ("Failed to open scratch file: %s\n", error->message);
+ return;
+ }
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gchar buffer [BUFFER_SIZE];
+ gsize bytes_read;
+
+ if (!g_input_stream_read_all (input_stream, buffer, BUFFER_SIZE, &bytes_read, NULL, &error) ||
+ bytes_read < BUFFER_SIZE)
+ {
+ g_printerr ("Failed to read back scratch file: %s\n", error->message);
+ g_input_stream_close (input_stream, NULL, NULL);
+ g_object_unref (input_stream);
+ }
+ }
+
+ g_object_unref (input_stream);
+}
+
+static void
+delete_file (GFile *scratch_file)
+{
+#if 0
+ GError *error = NULL;
+
+ /* Enable when GDaemonFile supports delete */
+
+ if (!g_file_delete (scratch_file, NULL, &error))
+ {
+ g_printerr ("Failed to delete scratch file: %s\n", error->message);
+ }
+#endif
+}
+
+static gint
+benchmark_run (gint argc, gchar *argv [])
+{
+ GFile *base_dir;
+ GFile *scratch_file;
+ gint i;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ if (argc < 2)
+ {
+ g_printerr ("Usage: %s <scratch URI>\n", argv [0]);
+ return 1;
+ }
+
+ base_dir = g_file_new_for_commandline_arg (argv [1]);
+
+ if (!is_dir (base_dir))
+ {
+ g_printerr ("Scratch URI %s is not a directory\n", argv [1]);
+ g_object_unref (base_dir);
+ return 1;
+ }
+
+ for (i = 0; i < ITERATIONS_NUM; i++)
+ {
+ scratch_file = create_file (base_dir);
+ if (!scratch_file)
+ {
+ g_object_unref (base_dir);
+ return 1;
+ }
+
+ read_file (scratch_file);
+ delete_file (scratch_file);
+
+ g_object_unref (scratch_file);
+ }
+
+ g_object_unref (base_dir);
+ return 0;
+}
diff --git a/trunk/test/benchmark-gvfs-small-files.c b/trunk/test/benchmark-gvfs-small-files.c
new file mode 100644
index 00000000..2e3143dd
--- /dev/null
+++ b/trunk/test/benchmark-gvfs-small-files.c
@@ -0,0 +1,191 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define BENCHMARK_UNIT_NAME "gvfs-big-file"
+
+#include "benchmark-common.c"
+
+#define FILE_SIZE 4096
+#define BUFFER_SIZE 4096
+#define ITERATIONS_NUM 65536
+
+static gboolean
+is_dir (GFile *file)
+{
+ GFileInfo *info;
+ gboolean res;
+
+ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
+ res = info && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ if (info)
+ g_object_unref (info);
+ return res;
+}
+
+static GFile *
+create_file (GFile *base_dir)
+{
+ GFile *scratch_file;
+ gchar *scratch_name;
+ GOutputStream *output_stream;
+ gint pid;
+ GError *error = NULL;
+ gchar buffer [BUFFER_SIZE];
+ gint i;
+
+ pid = getpid ();
+ scratch_name = g_strdup_printf ("gvfs-benchmark-scratch-%d", pid);
+ scratch_file = g_file_resolve_relative_path (base_dir, scratch_name);
+ g_free (scratch_name);
+
+ if (!scratch_file)
+ return NULL;
+
+ output_stream = G_OUTPUT_STREAM (g_file_replace (scratch_file, 0, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+ if (!output_stream)
+ {
+ g_printerr ("Failed to create scratch file: %s\n", error->message);
+ g_object_unref (scratch_file);
+ return NULL;
+ }
+
+ memset (buffer, 0xaa, BUFFER_SIZE);
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ if (g_output_stream_write (output_stream, buffer, BUFFER_SIZE, NULL, &error) < BUFFER_SIZE)
+ {
+ g_printerr ("Failed to populate scratch file: %s\n", error->message);
+ g_output_stream_close (output_stream, NULL, NULL);
+ g_object_unref (output_stream);
+ g_object_unref (scratch_file);
+ return NULL;
+ }
+ }
+
+ g_output_stream_close (output_stream, NULL, NULL);
+ g_object_unref (output_stream);
+ return scratch_file;
+}
+
+static void
+read_file (GFile *scratch_file)
+{
+ GInputStream *input_stream;
+ GError *error = NULL;
+ gint i;
+
+ input_stream = (GInputStream *) g_file_read (scratch_file, NULL, &error);
+ if (!input_stream)
+ {
+ g_printerr ("Failed to open scratch file: %s\n", error->message);
+ return;
+ }
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gchar buffer [BUFFER_SIZE];
+ gsize bytes_read;
+
+ if (!g_input_stream_read_all (input_stream, buffer, BUFFER_SIZE, &bytes_read, NULL, &error) ||
+ bytes_read < BUFFER_SIZE)
+ {
+ g_printerr ("Failed to read back scratch file: %s\n", error->message);
+ g_input_stream_close (input_stream, NULL, NULL);
+ g_object_unref (input_stream);
+ }
+ }
+
+ g_object_unref (input_stream);
+}
+
+static void
+delete_file (GFile *scratch_file)
+{
+#if 0
+ GError *error = NULL;
+
+ /* Enable when GDaemonFile supports delete */
+
+ if (!g_file_delete (scratch_file, NULL, &error))
+ {
+ g_printerr ("Failed to delete scratch file: %s\n", error->message);
+ }
+#endif
+}
+
+static gint
+benchmark_run (gint argc, gchar *argv [])
+{
+ GFile *base_dir;
+ GFile *scratch_file;
+ gint i;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ if (argc < 2)
+ {
+ g_printerr ("Usage: %s <scratch URI>\n", argv [0]);
+ return 1;
+ }
+
+ base_dir = g_file_new_for_commandline_arg (argv [1]);
+
+ if (!is_dir (base_dir))
+ {
+ g_printerr ("Scratch URI %s is not a directory\n", argv [1]);
+ g_object_unref (base_dir);
+ return 1;
+ }
+
+ for (i = 0; i < ITERATIONS_NUM; i++)
+ {
+ scratch_file = create_file (base_dir);
+ if (!scratch_file)
+ {
+ g_object_unref (base_dir);
+ return 1;
+ }
+
+ read_file (scratch_file);
+ delete_file (scratch_file);
+
+ g_object_unref (scratch_file);
+ }
+
+ g_object_unref (base_dir);
+ return 0;
+}
diff --git a/trunk/test/benchmark-posix-big-files.c b/trunk/test/benchmark-posix-big-files.c
new file mode 100644
index 00000000..86b3c349
--- /dev/null
+++ b/trunk/test/benchmark-posix-big-files.c
@@ -0,0 +1,192 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define BENCHMARK_UNIT_NAME "posix-big-file"
+
+#include "benchmark-common.c"
+
+#define FILE_SIZE (1024 * 1024 * 50) /* 50 MiB */
+#define BUFFER_SIZE 4096
+#define ITERATIONS_NUM 1
+
+static gboolean
+is_dir (const gchar *dir)
+{
+ struct stat sbuf;
+
+ if (stat (dir, &sbuf) < 0)
+ return FALSE;
+
+ if (S_ISDIR (sbuf.st_mode))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gchar *
+create_file (const gchar *base_dir)
+{
+ gchar *scratch_file;
+ gint output_fd;
+ gint pid;
+ gchar buffer [BUFFER_SIZE];
+ gint i;
+
+ pid = getpid ();
+ scratch_file = g_strdup_printf ("%s/posix-benchmark-scratch-%d", base_dir, pid);
+
+ output_fd = open (scratch_file, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+ if (output_fd < 0)
+ {
+ g_printerr ("Failed to create scratch file: %s\n", g_strerror (errno));
+ g_free (scratch_file);
+ return NULL;
+ }
+
+ memset (buffer, 0xaa, BUFFER_SIZE);
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gint bytes_written;
+
+ bytes_written = write (output_fd, buffer, BUFFER_SIZE);
+ if (bytes_written < BUFFER_SIZE)
+ {
+ if (errno == EINTR)
+ {
+ i -= BUFFER_SIZE - bytes_written;
+ continue;
+ }
+
+ g_printerr ("Failed to populate scratch file: %s\n", g_strerror (errno));
+ close (output_fd);
+ g_free (scratch_file);
+ return NULL;
+ }
+ }
+
+ close (output_fd);
+ return scratch_file;
+}
+
+static void
+read_file (const gchar *scratch_file)
+{
+ gint input_fd;
+ gint i;
+
+ input_fd = open (scratch_file, O_RDONLY);
+ if (input_fd < 0)
+ {
+ g_printerr ("Failed to read back scratch file: %s\n", g_strerror (errno));
+ return;
+ }
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gchar buffer [BUFFER_SIZE];
+ gsize bytes_read;
+
+ bytes_read = read (input_fd, buffer, BUFFER_SIZE);
+ if (bytes_read < BUFFER_SIZE)
+ {
+ if (errno == EINTR)
+ {
+ i -= BUFFER_SIZE - bytes_read;
+ continue;
+ }
+
+ g_printerr ("Failed to read back scratch file: %s\n", g_strerror (errno));
+ close (input_fd);
+ return;
+ }
+ }
+
+ close (input_fd);
+}
+
+static void
+delete_file (const gchar *scratch_file)
+{
+ if (unlink (scratch_file) < 0)
+ {
+ g_printerr ("Failed to delete scratch file: %s\n", g_strerror (errno));
+ }
+}
+
+static gint
+benchmark_run (gint argc, gchar *argv [])
+{
+ gchar *base_dir;
+ gchar *scratch_file;
+ gint i;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ if (argc < 2)
+ {
+ g_printerr ("Usage: %s <scratch path>\n", argv [0]);
+ return 1;
+ }
+
+ base_dir = argv [1];
+
+ if (!is_dir (base_dir))
+ {
+ g_printerr ("Scratch path %s is not a directory\n", argv [1]);
+ return 1;
+ }
+
+ for (i = 0; i < ITERATIONS_NUM; i++)
+ {
+ scratch_file = create_file (base_dir);
+ if (!scratch_file)
+ {
+ g_free (base_dir);
+ return 1;
+ }
+
+ read_file (scratch_file);
+ delete_file (scratch_file);
+
+ g_free (scratch_file);
+ }
+
+ return 0;
+}
diff --git a/trunk/test/benchmark-posix-small-files.c b/trunk/test/benchmark-posix-small-files.c
new file mode 100644
index 00000000..e3a99cfc
--- /dev/null
+++ b/trunk/test/benchmark-posix-small-files.c
@@ -0,0 +1,192 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define BENCHMARK_UNIT_NAME "posix-big-file"
+
+#include "benchmark-common.c"
+
+#define FILE_SIZE 4096
+#define BUFFER_SIZE 4096
+#define ITERATIONS_NUM 65536
+
+static gboolean
+is_dir (const gchar *dir)
+{
+ struct stat sbuf;
+
+ if (stat (dir, &sbuf) < 0)
+ return FALSE;
+
+ if (S_ISDIR (sbuf.st_mode))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gchar *
+create_file (const gchar *base_dir)
+{
+ gchar *scratch_file;
+ gint output_fd;
+ gint pid;
+ gchar buffer [BUFFER_SIZE];
+ gint i;
+
+ pid = getpid ();
+ scratch_file = g_strdup_printf ("%s/posix-benchmark-scratch-%d", base_dir, pid);
+
+ output_fd = open (scratch_file, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+ if (output_fd < 0)
+ {
+ g_printerr ("Failed to create scratch file: %s\n", g_strerror (errno));
+ g_free (scratch_file);
+ return NULL;
+ }
+
+ memset (buffer, 0xaa, BUFFER_SIZE);
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gint bytes_written;
+
+ bytes_written = write (output_fd, buffer, BUFFER_SIZE);
+ if (bytes_written < BUFFER_SIZE)
+ {
+ if (errno == EINTR)
+ {
+ i -= BUFFER_SIZE - bytes_written;
+ continue;
+ }
+
+ g_printerr ("Failed to populate scratch file: %s\n", g_strerror (errno));
+ close (output_fd);
+ g_free (scratch_file);
+ return NULL;
+ }
+ }
+
+ close (output_fd);
+ return scratch_file;
+}
+
+static void
+read_file (const gchar *scratch_file)
+{
+ gint input_fd;
+ gint i;
+
+ input_fd = open (scratch_file, O_RDONLY);
+ if (input_fd < 0)
+ {
+ g_printerr ("Failed to read back scratch file: %s\n", g_strerror (errno));
+ return;
+ }
+
+ for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE)
+ {
+ gchar buffer [BUFFER_SIZE];
+ gsize bytes_read;
+
+ bytes_read = read (input_fd, buffer, BUFFER_SIZE);
+ if (bytes_read < BUFFER_SIZE)
+ {
+ if (errno == EINTR)
+ {
+ i -= BUFFER_SIZE - bytes_read;
+ continue;
+ }
+
+ g_printerr ("Failed to read back scratch file: %s\n", g_strerror (errno));
+ close (input_fd);
+ return;
+ }
+ }
+
+ close (input_fd);
+}
+
+static void
+delete_file (const gchar *scratch_file)
+{
+ if (unlink (scratch_file) < 0)
+ {
+ g_printerr ("Failed to delete scratch file: %s\n", g_strerror (errno));
+ }
+}
+
+static gint
+benchmark_run (gint argc, gchar *argv [])
+{
+ gchar *base_dir;
+ gchar *scratch_file;
+ gint i;
+
+ setlocale (LC_ALL, "");
+
+ g_type_init ();
+
+ if (argc < 2)
+ {
+ g_printerr ("Usage: %s <scratch path>\n", argv [0]);
+ return 1;
+ }
+
+ base_dir = argv [1];
+
+ if (!is_dir (base_dir))
+ {
+ g_printerr ("Scratch path %s is not a directory\n", argv [1]);
+ return 1;
+ }
+
+ for (i = 0; i < ITERATIONS_NUM; i++)
+ {
+ scratch_file = create_file (base_dir);
+ if (!scratch_file)
+ {
+ g_free (base_dir);
+ return 1;
+ }
+
+ read_file (scratch_file);
+ delete_file (scratch_file);
+
+ g_free (scratch_file);
+ }
+
+ return 0;
+}
diff --git a/trunk/test/test-query-info-stream.c b/trunk/test/test-query-info-stream.c
new file mode 100644
index 00000000..d1288900
--- /dev/null
+++ b/trunk/test/test-query-info-stream.c
@@ -0,0 +1,294 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+/* Fill test data with 0..200, repeadedly.
+ * This is not a power of two to avoid possible
+ * effects with base-2 i/o buffer sizes that could
+ * hide bugs */
+#define DATA_MODULO 200
+
+static GMainLoop *main_loop;
+
+static gboolean
+verify_block (guchar *data, guchar *start, gsize size)
+{
+ guchar d;
+ gsize i;
+
+ d = 0;
+ if (start)
+ d = *start;
+ for (i = 0; i < size; i++)
+ {
+ if (data[i] != d)
+ return FALSE;
+
+ d++;
+ if (d >= DATA_MODULO)
+ d = 0;
+ }
+
+ if (start)
+ *start = d;
+
+ return TRUE;
+}
+
+static guchar *
+allocate_block (gsize size)
+{
+ guchar *data;
+ gsize i;
+ guchar d;
+
+ data = g_malloc (size);
+ d = 0;
+ for (i = 0; i < size; i++)
+ {
+ data[i] = d;
+ d++;
+ if (d >= DATA_MODULO)
+ d = 0;
+ }
+ return data;
+}
+
+static void
+check_query_info_res (GFileInfo *info,
+ GError *error,
+ gsize expected_size)
+{
+ goffset file_size;
+
+ if (info == NULL)
+ {
+ g_print ("error querying info: %s\n", error->message);
+ exit (1);
+ }
+
+ if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
+ {
+ g_print ("couldn't read size attribute\n");
+ exit (1);
+ }
+
+ file_size = g_file_info_get_size (info);
+ if (file_size != expected_size)
+ {
+ g_print ("wrong file size\n");
+ exit (1);
+ }
+}
+
+static void
+check_query_info_out (GFileOutputStream *out, gsize expected_size)
+{
+ GFileInfo *info;
+ GError *error;
+
+ error = NULL;
+ info = g_file_output_stream_query_info (out, "*", NULL, &error);
+
+ check_query_info_res (info, error, expected_size);
+}
+
+static void
+create_file (GFile *file, gsize size)
+{
+ GFileOutputStream *out;
+ guchar *data;
+ gsize written;
+ GError *error;
+
+ data = allocate_block (size);
+
+ error = NULL;
+ out = g_file_replace (file, NULL, FALSE, 0, NULL, &error);
+ if (out == NULL)
+ {
+ g_print ("error creating file: %s\n", error->message);
+ exit (1);
+ }
+
+ check_query_info_out (out, 0);
+
+ if (!g_output_stream_write_all (G_OUTPUT_STREAM (out),
+ data, size,
+ &written,
+ NULL, &error))
+ {
+ g_print ("error writing to file: %s\n", error->message);
+ exit (1);
+ }
+
+ check_query_info_out (out, written);
+
+ if (written != size)
+ {
+ g_print ("not all data written to file\n");
+ exit (1);
+ }
+
+ g_output_stream_close (G_OUTPUT_STREAM (out), NULL, NULL);
+
+ g_free (data);
+}
+
+static void
+check_query_info (GFileInputStream *in, gsize expected_size)
+{
+ GFileInfo *info;
+ GError *error;
+
+ error = NULL;
+ info = g_file_input_stream_query_info (in, "*", NULL, &error);
+
+ check_query_info_res (info, error, expected_size);
+}
+
+static void
+async_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GFileInfo *info;
+ GError *error;
+
+ error = NULL;
+ info =
+ g_file_input_stream_query_info_finish (G_FILE_INPUT_STREAM (source_object),
+ res, &error);
+
+ check_query_info_res (info, error, 100*1000);
+
+ g_main_loop_quit (main_loop);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GFile *file;
+ GFileInputStream *in;
+ GError *error;
+ gssize res;
+ gsize read_size;
+ guchar *buffer;
+ guchar start;
+ gboolean do_create_file;
+
+ g_type_init ();
+
+ do_create_file = FALSE;
+
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "-c") == 0)
+ {
+ do_create_file = TRUE;
+ argc--;
+ argv++;
+ }
+ }
+
+ if (argc != 2)
+ {
+ g_print ("need file arg");
+ return 1;
+ }
+
+ file = g_file_new_for_commandline_arg (argv[1]);
+
+ if (do_create_file)
+ create_file (file, 100*1000);
+
+ error = NULL;
+
+ in = g_file_read (file, NULL, &error);
+ if (in == NULL)
+ {
+ g_print ("error reading file: %s\n", error->message);
+ exit (1);
+ }
+
+ check_query_info (in, 100*1000);
+
+ buffer = malloc (100*1000);
+
+ start = 0;
+ read_size = 0;
+ do
+ {
+ res = g_input_stream_read (G_INPUT_STREAM (in),
+ buffer,
+ 150,
+ NULL, &error);
+ if (res == 0)
+ break;
+
+ if (res < 0)
+ {
+ g_print ("error reading: %s\n", error->message);
+ exit (1);
+ }
+
+ if (!verify_block (buffer, &start, res))
+ {
+ g_print ("error in block starting at %d\n", (int)read_size);
+ exit (1);
+ }
+
+ read_size += res;
+
+ check_query_info (in, 100*1000);
+ }
+ while (1);
+
+ if (read_size != 100*1000)
+ {
+ g_print ("Didn't read entire file\n");
+ exit (1);
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ g_file_input_stream_query_info_async (in, "*",
+ 0, NULL,
+ async_cb, NULL);
+
+ g_main_loop_run (main_loop);
+
+ g_print ("ALL OK\n");
+ return 0;
+}
diff --git a/trunk/txt/gvfs_dbus.txt b/trunk/txt/gvfs_dbus.txt
new file mode 100644
index 00000000..86ac19ac
--- /dev/null
+++ b/trunk/txt/gvfs_dbus.txt
@@ -0,0 +1,65 @@
+how to chain to simple stuff
+
+how to parse uris (i.e. map to mounts)
+
+what connections do we have:
+shared dbus connection
+connection to main daemom
+connection to each mount daemon
+
+"fast ops" (uri->gfile) vs blocking ops (read, open etc) and how to avoid slow blocking fast
+
+
+each thread has, on demand:
+connection to main daemon
+connection to some mount daemons
+
+global state:
+cache of previously used mountpoints
+
+
+how to mount
+
+how to store/restore permanent mounts with the session => store as drives (mountpoints), not volumes!
+
+Don't always want to log in to all mounts on login? (mounpoints!)
+
+computer:// handled in main daemon?
+
+No volume monitor in public API, only computer:// ?
+Problems:
+* mounted (desktop/computer:, trash dir)
+* unmounted/pre_unmount (desktop/computer:, close windows on unmounted volumes, trash dir)
+* map path to volume (close windows on unmounted volumes, check for readonly mount, get volume name)
+* get all drives/volumes (detecting where to show eject, mount, unmount menu items,
+ tree view, places sidebar, display volume icon in pathbar)
+* eject/unmount ops
+* needs eject
+
+unmounted URI => return a mountpoint object?
+
+GMountOperation, async mount operation object
+signals => passwd, question, keyring?
+
+GFile mountpoint => GMountOperation
+
+What process calls gnome-keyring?
+
+
+
+--------------------
+
+GFile creation => decompose URI, no i/o
+
+on i/o:
+ * figure out mountpoint (for now, always toplevel uri location)
+ * if we have a local dbus connection to that, use it, otherwise:
+ + create (if needed) local session dbus connection
+ + ask for mount daemon for new session
+ - If not existing, error on i/o, return mountpoint type on get_info
+ + set up new local connection with the mount daemon
+ * send dbus message
+ * recieve answer, if has magic flag, followed by fd sendmsg() (created by socketpair())
+
+
+
diff --git a/trunk/txt/ops.txt b/trunk/txt/ops.txt
new file mode 100644
index 00000000..c1f04c34
--- /dev/null
+++ b/trunk/txt/ops.txt
@@ -0,0 +1,140 @@
+type: File, Folder, Symlink, Shortcut, Mountable, special (fifo, socket, chardec, blockdev)
+flags: hidden,
+GFileInfo {
+ type get_type()
+ char *get_name()
+ char *get_display_name()
+ char *get_icon() /* string? what about win32, remote icons etc */
+
+ gint64 get_file_size()
+ char *get_mime_type()
+ char *get_link_target()
+ can_read()/write()/delete()/rename()/maybe: move()/copy()
+ flags get_flags()
+ time_t get_modification_time()
+ gboolean get_unix_stat ()
+ char *get_attribute()
+ char **get_attributes(char *namespace)
+ char **get_all_attributes() /* form namespace:attrname -> string */
+}
+
+GFSInfo {
+ char *get_fs_type()
+ gint64 get_free_space()
+ gint64 get_total_space()
+ char * get_hal_uid()
+ can_unmount()
+ can_eject()
+ must_eject()
+
+}
+
+GFile *g_file_for_path (char *path)
+GFile *g_file_for_uri (char *uri)
+GFile *g_file_parse_display_name (char *display_name)
+
+GFile {
+ char *get_path()
+ is_native() => is_file:///
+
+ char *get_uri ();
+ char *get_absolute_display_name ()
+
+ set_keep_open(boolean keep_open)
+
+ GFile *get_parent ()
+ GFile *get_child (char *name)
+ GFileEnumerator *enumerate_children(flags, attributes... "*", "vfs:*;dav:*;foo:bar")
+ GFileInfo *get_info (flags, attributes...)
+
+ void reload()
+ GInputStream *read()
+
+ GOutputStream *append_to() /* optional (not on webdav) */
+ GOutputStream *create()
+ GSaveStream *replace(mtime, backup_name, )
+/* permissions are all set minus umask, except replace which
+ saves old permissions */
+
+/* ?? */
+ GFile *resolve_symlink(char *symlink_target);
+
+/* output ops */
+ write/save
+ rename
+ move
+ copy
+ delete
+ mkdir
+ rmkdir
+ display name -> filename (for new files)
+ set attrs
+
+ /* other ops: */
+ monitor(flags) + signals
+ mount/unmount
+ list volumes
+
+ Maybe:
+ GFile *new_from_uri(path, flags) (file:/// uris)
+
+}
+
+
+names:
+ URIs == raw filename (no encoding), all escaped
+ We generate display absolute paths as filenames if possible, otherwise
+ as IRIs. This means we can display nice URIs for native utf8 backends
+ and filenames. However, URIs for non-utf8 shares will look bad. If we know
+ the encoding we can still get nice non-absolut display names though.
+
+ In client we store names as mountpoint + non-escaped no-encoding string.
+ Non-uri display name handling done in daemon
+
+GStatable iface for fstat() support
+GSaveStream, with get_final_file_info()
+
+open for writing:
+
+append vs truncate
+fail on existing or replace
+
+mtime match
+mtime return
+backup (suffix+prefix)
+create filename from display name
+unique name
+keep inode or be atomic?
+
+filename_for_display_name()
+write_append() /* optional (not on webdav) */
+write_new()
+write_replace()
+
+
+
+
+ftp supports:
+ overwrite
+ append
+ generate unique name
+
+http+webdav supports:
+ overwrite
+ append in recent versions
+ get mtime, length, mimetype, atime on read open
+
+
+
+
+
+async thread work:
+
+function to run in thread
+data to pass to thread
+cancel identifier
+pass in cancel func + data
+way for function to communicate with mainloop (of specific context)
+does mainloop notifiers block on ack?
+
+
diff --git a/trunk/txt/rfc3986.txt b/trunk/txt/rfc3986.txt
new file mode 100644
index 00000000..c56ed4eb
--- /dev/null
+++ b/trunk/txt/rfc3986.txt
@@ -0,0 +1,3419 @@
+
+
+
+
+
+
+Network Working Group T. Berners-Lee
+Request for Comments: 3986 W3C/MIT
+STD: 66 R. Fielding
+Updates: 1738 Day Software
+Obsoletes: 2732, 2396, 1808 L. Masinter
+Category: Standards Track Adobe Systems
+ January 2005
+
+
+ Uniform Resource Identifier (URI): Generic Syntax
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ A Uniform Resource Identifier (URI) is a compact sequence of
+ characters that identifies an abstract or physical resource. This
+ specification defines the generic URI syntax and a process for
+ resolving URI references that might be in relative form, along with
+ guidelines and security considerations for the use of URIs on the
+ Internet. The URI syntax defines a grammar that is a superset of all
+ valid URIs, allowing an implementation to parse the common components
+ of a URI reference without knowing the scheme-specific requirements
+ of every possible identifier. This specification does not define a
+ generative grammar for URIs; that task is performed by the individual
+ specifications of each URI scheme.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 1]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Overview of URIs . . . . . . . . . . . . . . . . . . . . 4
+ 1.1.1. Generic Syntax . . . . . . . . . . . . . . . . . 6
+ 1.1.2. Examples . . . . . . . . . . . . . . . . . . . . 7
+ 1.1.3. URI, URL, and URN . . . . . . . . . . . . . . . 7
+ 1.2. Design Considerations . . . . . . . . . . . . . . . . . 8
+ 1.2.1. Transcription . . . . . . . . . . . . . . . . . 8
+ 1.2.2. Separating Identification from Interaction . . . 9
+ 1.2.3. Hierarchical Identifiers . . . . . . . . . . . . 10
+ 1.3. Syntax Notation . . . . . . . . . . . . . . . . . . . . 11
+ 2. Characters . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 2.1. Percent-Encoding . . . . . . . . . . . . . . . . . . . . 12
+ 2.2. Reserved Characters . . . . . . . . . . . . . . . . . . 12
+ 2.3. Unreserved Characters . . . . . . . . . . . . . . . . . 13
+ 2.4. When to Encode or Decode . . . . . . . . . . . . . . . . 14
+ 2.5. Identifying Data . . . . . . . . . . . . . . . . . . . . 14
+ 3. Syntax Components . . . . . . . . . . . . . . . . . . . . . . 16
+ 3.1. Scheme . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2. Authority . . . . . . . . . . . . . . . . . . . . . . . 17
+ 3.2.1. User Information . . . . . . . . . . . . . . . . 18
+ 3.2.2. Host . . . . . . . . . . . . . . . . . . . . . . 18
+ 3.2.3. Port . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.3. Path . . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 3.4. Query . . . . . . . . . . . . . . . . . . . . . . . . . 23
+ 3.5. Fragment . . . . . . . . . . . . . . . . . . . . . . . . 24
+ 4. Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 4.1. URI Reference . . . . . . . . . . . . . . . . . . . . . 25
+ 4.2. Relative Reference . . . . . . . . . . . . . . . . . . . 26
+ 4.3. Absolute URI . . . . . . . . . . . . . . . . . . . . . . 27
+ 4.4. Same-Document Reference . . . . . . . . . . . . . . . . 27
+ 4.5. Suffix Reference . . . . . . . . . . . . . . . . . . . . 27
+ 5. Reference Resolution . . . . . . . . . . . . . . . . . . . . . 28
+ 5.1. Establishing a Base URI . . . . . . . . . . . . . . . . 28
+ 5.1.1. Base URI Embedded in Content . . . . . . . . . . 29
+ 5.1.2. Base URI from the Encapsulating Entity . . . . . 29
+ 5.1.3. Base URI from the Retrieval URI . . . . . . . . 30
+ 5.1.4. Default Base URI . . . . . . . . . . . . . . . . 30
+ 5.2. Relative Resolution . . . . . . . . . . . . . . . . . . 30
+ 5.2.1. Pre-parse the Base URI . . . . . . . . . . . . . 31
+ 5.2.2. Transform References . . . . . . . . . . . . . . 31
+ 5.2.3. Merge Paths . . . . . . . . . . . . . . . . . . 32
+ 5.2.4. Remove Dot Segments . . . . . . . . . . . . . . 33
+ 5.3. Component Recomposition . . . . . . . . . . . . . . . . 35
+ 5.4. Reference Resolution Examples . . . . . . . . . . . . . 35
+ 5.4.1. Normal Examples . . . . . . . . . . . . . . . . 36
+ 5.4.2. Abnormal Examples . . . . . . . . . . . . . . . 36
+
+
+
+Berners-Lee, et al. Standards Track [Page 2]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ 6. Normalization and Comparison . . . . . . . . . . . . . . . . . 38
+ 6.1. Equivalence . . . . . . . . . . . . . . . . . . . . . . 38
+ 6.2. Comparison Ladder . . . . . . . . . . . . . . . . . . . 39
+ 6.2.1. Simple String Comparison . . . . . . . . . . . . 39
+ 6.2.2. Syntax-Based Normalization . . . . . . . . . . . 40
+ 6.2.3. Scheme-Based Normalization . . . . . . . . . . . 41
+ 6.2.4. Protocol-Based Normalization . . . . . . . . . . 42
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 43
+ 7.1. Reliability and Consistency . . . . . . . . . . . . . . 43
+ 7.2. Malicious Construction . . . . . . . . . . . . . . . . . 43
+ 7.3. Back-End Transcoding . . . . . . . . . . . . . . . . . . 44
+ 7.4. Rare IP Address Formats . . . . . . . . . . . . . . . . 45
+ 7.5. Sensitive Information . . . . . . . . . . . . . . . . . 45
+ 7.6. Semantic Attacks . . . . . . . . . . . . . . . . . . . . 45
+ 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 46
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 46
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 46
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 47
+ A. Collected ABNF for URI . . . . . . . . . . . . . . . . . . . . 49
+ B. Parsing a URI Reference with a Regular Expression . . . . . . 50
+ C. Delimiting a URI in Context . . . . . . . . . . . . . . . . . 51
+ D. Changes from RFC 2396 . . . . . . . . . . . . . . . . . . . . 53
+ D.1. Additions . . . . . . . . . . . . . . . . . . . . . . . 53
+ D.2. Modifications . . . . . . . . . . . . . . . . . . . . . 53
+ Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 60
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 61
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 3]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1. Introduction
+
+ A Uniform Resource Identifier (URI) provides a simple and extensible
+ means for identifying a resource. This specification of URI syntax
+ and semantics is derived from concepts introduced by the World Wide
+ Web global information initiative, whose use of these identifiers
+ dates from 1990 and is described in "Universal Resource Identifiers
+ in WWW" [RFC1630]. The syntax is designed to meet the
+ recommendations laid out in "Functional Recommendations for Internet
+ Resource Locators" [RFC1736] and "Functional Requirements for Uniform
+ Resource Names" [RFC1737].
+
+ This document obsoletes [RFC2396], which merged "Uniform Resource
+ Locators" [RFC1738] and "Relative Uniform Resource Locators"
+ [RFC1808] in order to define a single, generic syntax for all URIs.
+ It obsoletes [RFC2732], which introduced syntax for an IPv6 address.
+ It excludes portions of RFC 1738 that defined the specific syntax of
+ individual URI schemes; those portions will be updated as separate
+ documents. The process for registration of new URI schemes is
+ defined separately by [BCP35]. Advice for designers of new URI
+ schemes can be found in [RFC2718]. All significant changes from RFC
+ 2396 are noted in Appendix D.
+
+ This specification uses the terms "character" and "coded character
+ set" in accordance with the definitions provided in [BCP19], and
+ "character encoding" in place of what [BCP19] refers to as a
+ "charset".
+
+1.1. Overview of URIs
+
+ URIs are characterized as follows:
+
+ Uniform
+
+ Uniformity provides several benefits. It allows different types
+ of resource identifiers to be used in the same context, even when
+ the mechanisms used to access those resources may differ. It
+ allows uniform semantic interpretation of common syntactic
+ conventions across different types of resource identifiers. It
+ allows introduction of new types of resource identifiers without
+ interfering with the way that existing identifiers are used. It
+ allows the identifiers to be reused in many different contexts,
+ thus permitting new applications or protocols to leverage a pre-
+ existing, large, and widely used set of resource identifiers.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 4]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Resource
+
+ This specification does not limit the scope of what might be a
+ resource; rather, the term "resource" is used in a general sense
+ for whatever might be identified by a URI. Familiar examples
+ include an electronic document, an image, a source of information
+ with a consistent purpose (e.g., "today's weather report for Los
+ Angeles"), a service (e.g., an HTTP-to-SMS gateway), and a
+ collection of other resources. A resource is not necessarily
+ accessible via the Internet; e.g., human beings, corporations, and
+ bound books in a library can also be resources. Likewise,
+ abstract concepts can be resources, such as the operators and
+ operands of a mathematical equation, the types of a relationship
+ (e.g., "parent" or "employee"), or numeric values (e.g., zero,
+ one, and infinity).
+
+ Identifier
+
+ An identifier embodies the information required to distinguish
+ what is being identified from all other things within its scope of
+ identification. Our use of the terms "identify" and "identifying"
+ refer to this purpose of distinguishing one resource from all
+ other resources, regardless of how that purpose is accomplished
+ (e.g., by name, address, or context). These terms should not be
+ mistaken as an assumption that an identifier defines or embodies
+ the identity of what is referenced, though that may be the case
+ for some identifiers. Nor should it be assumed that a system
+ using URIs will access the resource identified: in many cases,
+ URIs are used to denote resources without any intention that they
+ be accessed. Likewise, the "one" resource identified might not be
+ singular in nature (e.g., a resource might be a named set or a
+ mapping that varies over time).
+
+ A URI is an identifier consisting of a sequence of characters
+ matching the syntax rule named <URI> in Section 3. It enables
+ uniform identification of resources via a separately defined
+ extensible set of naming schemes (Section 3.1). How that
+ identification is accomplished, assigned, or enabled is delegated to
+ each scheme specification.
+
+ This specification does not place any limits on the nature of a
+ resource, the reasons why an application might seek to refer to a
+ resource, or the kinds of systems that might use URIs for the sake of
+ identifying resources. This specification does not require that a
+ URI persists in identifying the same resource over time, though that
+ is a common goal of all URI schemes. Nevertheless, nothing in this
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 5]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification prevents an application from limiting itself to
+ particular types of resources, or to a subset of URIs that maintains
+ characteristics desired by that application.
+
+ URIs have a global scope and are interpreted consistently regardless
+ of context, though the result of that interpretation may be in
+ relation to the end-user's context. For example, "http://localhost/"
+ has the same interpretation for every user of that reference, even
+ though the network interface corresponding to "localhost" may be
+ different for each end-user: interpretation is independent of access.
+ However, an action made on the basis of that reference will take
+ place in relation to the end-user's context, which implies that an
+ action intended to refer to a globally unique thing must use a URI
+ that distinguishes that resource from all other things. URIs that
+ identify in relation to the end-user's local context should only be
+ used when the context itself is a defining aspect of the resource,
+ such as when an on-line help manual refers to a file on the end-
+ user's file system (e.g., "file:///etc/hosts").
+
+1.1.1. Generic Syntax
+
+ Each URI begins with a scheme name, as defined in Section 3.1, that
+ refers to a specification for assigning identifiers within that
+ scheme. As such, the URI syntax is a federated and extensible naming
+ system wherein each scheme's specification may further restrict the
+ syntax and semantics of identifiers using that scheme.
+
+ This specification defines those elements of the URI syntax that are
+ required of all URI schemes or are common to many URI schemes. It
+ thus defines the syntax and semantics needed to implement a scheme-
+ independent parsing mechanism for URI references, by which the
+ scheme-dependent handling of a URI can be postponed until the
+ scheme-dependent semantics are needed. Likewise, protocols and data
+ formats that make use of URI references can refer to this
+ specification as a definition for the range of syntax allowed for all
+ URIs, including those schemes that have yet to be defined. This
+ decouples the evolution of identification schemes from the evolution
+ of protocols, data formats, and implementations that make use of
+ URIs.
+
+ A parser of the generic URI syntax can parse any URI reference into
+ its major components. Once the scheme is determined, further
+ scheme-specific parsing can be performed on the components. In other
+ words, the URI generic syntax is a superset of the syntax of all URI
+ schemes.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 6]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.1.2. Examples
+
+ The following example URIs illustrate several URI schemes and
+ variations in their common syntax components:
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+
+ http://www.ietf.org/rfc/rfc2396.txt
+
+ ldap://[2001:db8::7]/c=GB?objectClass?one
+
+ mailto:John.Doe@example.com
+
+ news:comp.infosystems.www.servers.unix
+
+ tel:+1-816-555-1212
+
+ telnet://192.0.2.16:80/
+
+ urn:oasis:names:specification:docbook:dtd:xml:4.1.2
+
+
+1.1.3. URI, URL, and URN
+
+ A URI can be further classified as a locator, a name, or both. The
+ term "Uniform Resource Locator" (URL) refers to the subset of URIs
+ that, in addition to identifying a resource, provide a means of
+ locating the resource by describing its primary access mechanism
+ (e.g., its network "location"). The term "Uniform Resource Name"
+ (URN) has been used historically to refer to both URIs under the
+ "urn" scheme [RFC2141], which are required to remain globally unique
+ and persistent even when the resource ceases to exist or becomes
+ unavailable, and to any other URI with the properties of a name.
+
+ An individual scheme does not have to be classified as being just one
+ of "name" or "locator". Instances of URIs from any given scheme may
+ have the characteristics of names or locators or both, often
+ depending on the persistence and care in the assignment of
+ identifiers by the naming authority, rather than on any quality of
+ the scheme. Future specifications and related documentation should
+ use the general term "URI" rather than the more restrictive terms
+ "URL" and "URN" [RFC3305].
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 7]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+1.2. Design Considerations
+
+1.2.1. Transcription
+
+ The URI syntax has been designed with global transcription as one of
+ its main considerations. A URI is a sequence of characters from a
+ very limited set: the letters of the basic Latin alphabet, digits,
+ and a few special characters. A URI may be represented in a variety
+ of ways; e.g., ink on paper, pixels on a screen, or a sequence of
+ character encoding octets. The interpretation of a URI depends only
+ on the characters used and not on how those characters are
+ represented in a network protocol.
+
+ The goal of transcription can be described by a simple scenario.
+ Imagine two colleagues, Sam and Kim, sitting in a pub at an
+ international conference and exchanging research ideas. Sam asks Kim
+ for a location to get more information, so Kim writes the URI for the
+ research site on a napkin. Upon returning home, Sam takes out the
+ napkin and types the URI into a computer, which then retrieves the
+ information to which Kim referred.
+
+ There are several design considerations revealed by the scenario:
+
+ o A URI is a sequence of characters that is not always represented
+ as a sequence of octets.
+
+ o A URI might be transcribed from a non-network source and thus
+ should consist of characters that are most likely able to be
+ entered into a computer, within the constraints imposed by
+ keyboards (and related input devices) across languages and
+ locales.
+
+ o A URI often has to be remembered by people, and it is easier for
+ people to remember a URI when it consists of meaningful or
+ familiar components.
+
+ These design considerations are not always in alignment. For
+ example, it is often the case that the most meaningful name for a URI
+ component would require characters that cannot be typed into some
+ systems. The ability to transcribe a resource identifier from one
+ medium to another has been considered more important than having a
+ URI consist of the most meaningful of components.
+
+ In local or regional contexts and with improving technology, users
+ might benefit from being able to use a wider range of characters;
+ such use is not defined by this specification. Percent-encoded
+ octets (Section 2.1) may be used within a URI to represent characters
+ outside the range of the US-ASCII coded character set if this
+
+
+
+Berners-Lee, et al. Standards Track [Page 8]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ representation is allowed by the scheme or by the protocol element in
+ which the URI is referenced. Such a definition should specify the
+ character encoding used to map those characters to octets prior to
+ being percent-encoded for the URI.
+
+1.2.2. Separating Identification from Interaction
+
+ A common misunderstanding of URIs is that they are only used to refer
+ to accessible resources. The URI itself only provides
+ identification; access to the resource is neither guaranteed nor
+ implied by the presence of a URI. Instead, any operation associated
+ with a URI reference is defined by the protocol element, data format
+ attribute, or natural language text in which it appears.
+
+ Given a URI, a system may attempt to perform a variety of operations
+ on the resource, as might be characterized by words such as "access",
+ "update", "replace", or "find attributes". Such operations are
+ defined by the protocols that make use of URIs, not by this
+ specification. However, we do use a few general terms for describing
+ common operations on URIs. URI "resolution" is the process of
+ determining an access mechanism and the appropriate parameters
+ necessary to dereference a URI; this resolution may require several
+ iterations. To use that access mechanism to perform an action on the
+ URI's resource is to "dereference" the URI.
+
+ When URIs are used within information retrieval systems to identify
+ sources of information, the most common form of URI dereference is
+ "retrieval": making use of a URI in order to retrieve a
+ representation of its associated resource. A "representation" is a
+ sequence of octets, along with representation metadata describing
+ those octets, that constitutes a record of the state of the resource
+ at the time when the representation is generated. Retrieval is
+ achieved by a process that might include using the URI as a cache key
+ to check for a locally cached representation, resolution of the URI
+ to determine an appropriate access mechanism (if any), and
+ dereference of the URI for the sake of applying a retrieval
+ operation. Depending on the protocols used to perform the retrieval,
+ additional information might be supplied about the resource (resource
+ metadata) and its relation to other resources.
+
+ URI references in information retrieval systems are designed to be
+ late-binding: the result of an access is generally determined when it
+ is accessed and may vary over time or due to other aspects of the
+ interaction. These references are created in order to be used in the
+ future: what is being identified is not some specific result that was
+ obtained in the past, but rather some characteristic that is expected
+ to be true for future results. In such cases, the resource referred
+ to by the URI is actually a sameness of characteristics as observed
+
+
+
+Berners-Lee, et al. Standards Track [Page 9]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ over time, perhaps elucidated by additional comments or assertions
+ made by the resource provider.
+
+ Although many URI schemes are named after protocols, this does not
+ imply that use of these URIs will result in access to the resource
+ via the named protocol. URIs are often used simply for the sake of
+ identification. Even when a URI is used to retrieve a representation
+ of a resource, that access might be through gateways, proxies,
+ caches, and name resolution services that are independent of the
+ protocol associated with the scheme name. The resolution of some
+ URIs may require the use of more than one protocol (e.g., both DNS
+ and HTTP are typically used to access an "http" URI's origin server
+ when a representation isn't found in a local cache).
+
+1.2.3. Hierarchical Identifiers
+
+ The URI syntax is organized hierarchically, with components listed in
+ order of decreasing significance from left to right. For some URI
+ schemes, the visible hierarchy is limited to the scheme itself:
+ everything after the scheme component delimiter (":") is considered
+ opaque to URI processing. Other URI schemes make the hierarchy
+ explicit and visible to generic parsing algorithms.
+
+ The generic syntax uses the slash ("/"), question mark ("?"), and
+ number sign ("#") characters to delimit components that are
+ significant to the generic parser's hierarchical interpretation of an
+ identifier. In addition to aiding the readability of such
+ identifiers through the consistent use of familiar syntax, this
+ uniform representation of hierarchy across naming schemes allows
+ scheme-independent references to be made relative to that hierarchy.
+
+ It is often the case that a group or "tree" of documents has been
+ constructed to serve a common purpose, wherein the vast majority of
+ URI references in these documents point to resources within the tree
+ rather than outside it. Similarly, documents located at a particular
+ site are much more likely to refer to other resources at that site
+ than to resources at remote sites. Relative referencing of URIs
+ allows document trees to be partially independent of their location
+ and access scheme. For instance, it is possible for a single set of
+ hypertext documents to be simultaneously accessible and traversable
+ via each of the "file", "http", and "ftp" schemes if the documents
+ refer to each other with relative references. Furthermore, such
+ document trees can be moved, as a whole, without changing any of the
+ relative references.
+
+ A relative reference (Section 4.2) refers to a resource by describing
+ the difference within a hierarchical name space between the reference
+ context and the target URI. The reference resolution algorithm,
+
+
+
+Berners-Lee, et al. Standards Track [Page 10]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ presented in Section 5, defines how such a reference is transformed
+ to the target URI. As relative references can only be used within
+ the context of a hierarchical URI, designers of new URI schemes
+ should use a syntax consistent with the generic syntax's hierarchical
+ components unless there are compelling reasons to forbid relative
+ referencing within that scheme.
+
+ NOTE: Previous specifications used the terms "partial URI" and
+ "relative URI" to denote a relative reference to a URI. As some
+ readers misunderstood those terms to mean that relative URIs are a
+ subset of URIs rather than a method of referencing URIs, this
+ specification simply refers to them as relative references.
+
+ All URI references are parsed by generic syntax parsers when used.
+ However, because hierarchical processing has no effect on an absolute
+ URI used in a reference unless it contains one or more dot-segments
+ (complete path segments of "." or "..", as described in Section 3.3),
+ URI scheme specifications can define opaque identifiers by
+ disallowing use of slash characters, question mark characters, and
+ the URIs "scheme:." and "scheme:..".
+
+1.3. Syntax Notation
+
+ This specification uses the Augmented Backus-Naur Form (ABNF)
+ notation of [RFC2234], including the following core ABNF syntax rules
+ defined by that specification: ALPHA (letters), CR (carriage return),
+ DIGIT (decimal digits), DQUOTE (double quote), HEXDIG (hexadecimal
+ digits), LF (line feed), and SP (space). The complete URI syntax is
+ collected in Appendix A.
+
+2. Characters
+
+ The URI syntax provides a method of encoding data, presumably for the
+ sake of identifying a resource, as a sequence of characters. The URI
+ characters are, in turn, frequently encoded as octets for transport
+ or presentation. This specification does not mandate any particular
+ character encoding for mapping between URI characters and the octets
+ used to store or transmit those characters. When a URI appears in a
+ protocol element, the character encoding is defined by that protocol;
+ without such a definition, a URI is assumed to be in the same
+ character encoding as the surrounding text.
+
+ The ABNF notation defines its terminal values to be non-negative
+ integers (codepoints) based on the US-ASCII coded character set
+ [ASCII]. Because a URI is a sequence of characters, we must invert
+ that relation in order to understand the URI syntax. Therefore, the
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 11]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ integer values used by the ABNF must be mapped back to their
+ corresponding characters via US-ASCII in order to complete the syntax
+ rules.
+
+ A URI is composed from a limited set of characters consisting of
+ digits, letters, and a few graphic symbols. A reserved subset of
+ those characters may be used to delimit syntax components within a
+ URI while the remaining characters, including both the unreserved set
+ and those reserved characters not acting as delimiters, define each
+ component's identifying data.
+
+2.1. Percent-Encoding
+
+ A percent-encoding mechanism is used to represent a data octet in a
+ component when that octet's corresponding character is outside the
+ allowed set or is being used as a delimiter of, or within, the
+ component. A percent-encoded octet is encoded as a character
+ triplet, consisting of the percent character "%" followed by the two
+ hexadecimal digits representing that octet's numeric value. For
+ example, "%20" is the percent-encoding for the binary octet
+ "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space
+ character (SP). Section 2.4 describes when percent-encoding and
+ decoding is applied.
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ The uppercase hexadecimal digits 'A' through 'F' are equivalent to
+ the lowercase digits 'a' through 'f', respectively. If two URIs
+ differ only in the case of hexadecimal digits used in percent-encoded
+ octets, they are equivalent. For consistency, URI producers and
+ normalizers should use uppercase hexadecimal digits for all percent-
+ encodings.
+
+2.2. Reserved Characters
+
+ URIs include components and subcomponents that are delimited by
+ characters in the "reserved" set. These characters are called
+ "reserved" because they may (or may not) be defined as delimiters by
+ the generic syntax, by each scheme-specific syntax, or by the
+ implementation-specific syntax of a URI's dereferencing algorithm.
+ If data for a URI component would conflict with a reserved
+ character's purpose as a delimiter, then the conflicting data must be
+ percent-encoded before the URI is formed.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 12]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ reserved = gen-delims / sub-delims
+
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+ The purpose of reserved characters is to provide a set of delimiting
+ characters that are distinguishable from other data within a URI.
+ URIs that differ in the replacement of a reserved character with its
+ corresponding percent-encoded octet are not equivalent. Percent-
+ encoding a reserved character, or decoding a percent-encoded octet
+ that corresponds to a reserved character, will change how the URI is
+ interpreted by most applications. Thus, characters in the reserved
+ set are protected from normalization and are therefore safe to be
+ used by scheme-specific and producer-specific algorithms for
+ delimiting data subcomponents within a URI.
+
+ A subset of the reserved characters (gen-delims) is used as
+ delimiters of the generic URI components described in Section 3. A
+ component's ABNF syntax rule will not use the reserved or gen-delims
+ rule names directly; instead, each syntax rule lists the characters
+ allowed within that component (i.e., not delimiting it), and any of
+ those characters that are also in the reserved set are "reserved" for
+ use as subcomponent delimiters within the component. Only the most
+ common subcomponents are defined by this specification; other
+ subcomponents may be defined by a URI scheme's specification, or by
+ the implementation-specific syntax of a URI's dereferencing
+ algorithm, provided that such subcomponents are delimited by
+ characters in the reserved set allowed within that component.
+
+ URI producing applications should percent-encode data octets that
+ correspond to characters in the reserved set unless these characters
+ are specifically allowed by the URI scheme to represent data in that
+ component. If a reserved character is found in a URI component and
+ no delimiting role is known for that character, then it must be
+ interpreted as representing the data octet corresponding to that
+ character's encoding in US-ASCII.
+
+2.3. Unreserved Characters
+
+ Characters that are allowed in a URI but do not have a reserved
+ purpose are called unreserved. These include uppercase and lowercase
+ letters, decimal digits, hyphen, period, underscore, and tilde.
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 13]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URIs that differ in the replacement of an unreserved character with
+ its corresponding percent-encoded US-ASCII octet are equivalent: they
+ identify the same resource. However, URI comparison implementations
+ do not always perform normalization prior to comparison (see Section
+ 6). For consistency, percent-encoded octets in the ranges of ALPHA
+ (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),
+ underscore (%5F), or tilde (%7E) should not be created by URI
+ producers and, when found in a URI, should be decoded to their
+ corresponding unreserved characters by URI normalizers.
+
+2.4. When to Encode or Decode
+
+ Under normal circumstances, the only time when octets within a URI
+ are percent-encoded is during the process of producing the URI from
+ its component parts. This is when an implementation determines which
+ of the reserved characters are to be used as subcomponent delimiters
+ and which can be safely used as data. Once produced, a URI is always
+ in its percent-encoded form.
+
+ When a URI is dereferenced, the components and subcomponents
+ significant to the scheme-specific dereferencing process (if any)
+ must be parsed and separated before the percent-encoded octets within
+ those components can be safely decoded, as otherwise the data may be
+ mistaken for component delimiters. The only exception is for
+ percent-encoded octets corresponding to characters in the unreserved
+ set, which can be decoded at any time. For example, the octet
+ corresponding to the tilde ("~") character is often encoded as "%7E"
+ by older URI processing implementations; the "%7E" can be replaced by
+ "~" without changing its interpretation.
+
+ Because the percent ("%") character serves as the indicator for
+ percent-encoded octets, it must be percent-encoded as "%25" for that
+ octet to be used as data within a URI. Implementations must not
+ percent-encode or decode the same string more than once, as decoding
+ an already decoded string might lead to misinterpreting a percent
+ data octet as the beginning of a percent-encoding, or vice versa in
+ the case of percent-encoding an already percent-encoded string.
+
+2.5. Identifying Data
+
+ URI characters provide identifying data for each of the URI
+ components, serving as an external interface for identification
+ between systems. Although the presence and nature of the URI
+ production interface is hidden from clients that use its URIs (and is
+ thus beyond the scope of the interoperability requirements defined by
+ this specification), it is a frequent source of confusion and errors
+ in the interpretation of URI character issues. Implementers have to
+ be aware that there are multiple character encodings involved in the
+
+
+
+Berners-Lee, et al. Standards Track [Page 14]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ production and transmission of URIs: local name and data encoding,
+ public interface encoding, URI character encoding, data format
+ encoding, and protocol encoding.
+
+ Local names, such as file system names, are stored with a local
+ character encoding. URI producing applications (e.g., origin
+ servers) will typically use the local encoding as the basis for
+ producing meaningful names. The URI producer will transform the
+ local encoding to one that is suitable for a public interface and
+ then transform the public interface encoding into the restricted set
+ of URI characters (reserved, unreserved, and percent-encodings).
+ Those characters are, in turn, encoded as octets to be used as a
+ reference within a data format (e.g., a document charset), and such
+ data formats are often subsequently encoded for transmission over
+ Internet protocols.
+
+ For most systems, an unreserved character appearing within a URI
+ component is interpreted as representing the data octet corresponding
+ to that character's encoding in US-ASCII. Consumers of URIs assume
+ that the letter "X" corresponds to the octet "01011000", and even
+ when that assumption is incorrect, there is no harm in making it. A
+ system that internally provides identifiers in the form of a
+ different character encoding, such as EBCDIC, will generally perform
+ character translation of textual identifiers to UTF-8 [STD63] (or
+ some other superset of the US-ASCII character encoding) at an
+ internal interface, thereby providing more meaningful identifiers
+ than those resulting from simply percent-encoding the original
+ octets.
+
+ For example, consider an information service that provides data,
+ stored locally using an EBCDIC-based file system, to clients on the
+ Internet through an HTTP server. When an author creates a file with
+ the name "Laguna Beach" on that file system, the "http" URI
+ corresponding to that resource is expected to contain the meaningful
+ string "Laguna%20Beach". If, however, that server produces URIs by
+ using an overly simplistic raw octet mapping, then the result would
+ be a URI containing "%D3%81%87%A4%95%81@%C2%85%81%83%88". An
+ internal transcoding interface fixes this problem by transcoding the
+ local name to a superset of US-ASCII prior to producing the URI.
+ Naturally, proper interpretation of an incoming URI on such an
+ interface requires that percent-encoded octets be decoded (e.g.,
+ "%20" to SP) before the reverse transcoding is applied to obtain the
+ local name.
+
+ In some cases, the internal interface between a URI component and the
+ identifying data that it has been crafted to represent is much less
+ direct than a character encoding translation. For example, portions
+ of a URI might reflect a query on non-ASCII data, or numeric
+
+
+
+Berners-Lee, et al. Standards Track [Page 15]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ coordinates on a map. Likewise, a URI scheme may define components
+ with additional encoding requirements that are applied prior to
+ forming the component and producing the URI.
+
+ When a new URI scheme defines a component that represents textual
+ data consisting of characters from the Universal Character Set [UCS],
+ the data should first be encoded as octets according to the UTF-8
+ character encoding [STD63]; then only those octets that do not
+ correspond to characters in the unreserved set should be percent-
+ encoded. For example, the character A would be represented as "A",
+ the character LATIN CAPITAL LETTER A WITH GRAVE would be represented
+ as "%C3%80", and the character KATAKANA LETTER A would be represented
+ as "%E3%82%A2".
+
+3. Syntax Components
+
+ The generic URI syntax consists of a hierarchical sequence of
+ components referred to as the scheme, authority, path, query, and
+ fragment.
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ The scheme and path components are required, though the path may be
+ empty (no characters). When authority is present, the path must
+ either be empty or begin with a slash ("/") character. When
+ authority is not present, the path cannot begin with two slash
+ characters ("//"). These restrictions result in five different ABNF
+ rules for a path (Section 3.3), only one of which will match any
+ given URI reference.
+
+ The following are two example URIs and their component parts:
+
+ foo://example.com:8042/over/there?name=ferret#nose
+ \_/ \______________/\_________/ \_________/ \__/
+ | | | | |
+ scheme authority path query fragment
+ | _____________________|__
+ / \ / \
+ urn:example:animal:ferret:nose
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 16]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.1. Scheme
+
+ Each URI begins with a scheme name that refers to a specification for
+ assigning identifiers within that scheme. As such, the URI syntax is
+ a federated and extensible naming system wherein each scheme's
+ specification may further restrict the syntax and semantics of
+ identifiers using that scheme.
+
+ Scheme names consist of a sequence of characters beginning with a
+ letter and followed by any combination of letters, digits, plus
+ ("+"), period ("."), or hyphen ("-"). Although schemes are case-
+ insensitive, the canonical form is lowercase and documents that
+ specify schemes must do so with lowercase letters. An implementation
+ should accept uppercase letters as equivalent to lowercase in scheme
+ names (e.g., allow "HTTP" as well as "http") for the sake of
+ robustness but should only produce lowercase scheme names for
+ consistency.
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ Individual schemes are not specified by this document. The process
+ for registration of new URI schemes is defined separately by [BCP35].
+ The scheme registry maintains the mapping between scheme names and
+ their specifications. Advice for designers of new URI schemes can be
+ found in [RFC2718]. URI scheme specifications must define their own
+ syntax so that all strings matching their scheme-specific syntax will
+ also match the <absolute-URI> grammar, as described in Section 4.3.
+
+ When presented with a URI that violates one or more scheme-specific
+ restrictions, the scheme-specific resolution process should flag the
+ reference as an error rather than ignore the unused parts; doing so
+ reduces the number of equivalent URIs and helps detect abuses of the
+ generic syntax, which might indicate that the URI has been
+ constructed to mislead the user (Section 7.6).
+
+3.2. Authority
+
+ Many URI schemes include a hierarchical element for a naming
+ authority so that governance of the name space defined by the
+ remainder of the URI is delegated to that authority (which may, in
+ turn, delegate it further). The generic syntax provides a common
+ means for distinguishing an authority based on a registered name or
+ server address, along with optional port and user information.
+
+ The authority component is preceded by a double slash ("//") and is
+ terminated by the next slash ("/"), question mark ("?"), or number
+ sign ("#") character, or by the end of the URI.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 17]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+
+ URI producers and normalizers should omit the ":" delimiter that
+ separates host from port if the port component is empty. Some
+ schemes do not allow the userinfo and/or port subcomponents.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. Non-
+ validating parsers (those that merely separate a URI reference into
+ its major components) will often ignore the subcomponent structure of
+ authority, treating it as an opaque string from the double-slash to
+ the first terminating delimiter, until such time as the URI is
+ dereferenced.
+
+3.2.1. User Information
+
+ The userinfo subcomponent may consist of a user name and, optionally,
+ scheme-specific information about how to gain authorization to access
+ the resource. The user information, if present, is followed by a
+ commercial at-sign ("@") that delimits it from the host.
+
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+
+ Use of the format "user:password" in the userinfo field is
+ deprecated. Applications should not render as clear text any data
+ after the first colon (":") character found within a userinfo
+ subcomponent unless the data after the colon is the empty string
+ (indicating no password). Applications may choose to ignore or
+ reject such data when it is received as part of a reference and
+ should reject the storage of such data in unencrypted form. The
+ passing of authentication information in clear text has proven to be
+ a security risk in almost every case where it has been used.
+
+ Applications that render a URI for the sake of user feedback, such as
+ in graphical hypertext browsing, should render userinfo in a way that
+ is distinguished from the rest of a URI, when feasible. Such
+ rendering will assist the user in cases where the userinfo has been
+ misleadingly crafted to look like a trusted domain name
+ (Section 7.6).
+
+3.2.2. Host
+
+ The host subcomponent of authority is identified by an IP literal
+ encapsulated within square brackets, an IPv4 address in dotted-
+ decimal form, or a registered name. The host subcomponent is case-
+ insensitive. The presence of a host subcomponent within a URI does
+ not imply that the scheme requires access to the given host on the
+ Internet. In many cases, the host syntax is used only for the sake
+
+
+
+Berners-Lee, et al. Standards Track [Page 18]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ of reusing the existing registration process created and deployed for
+ DNS, thus obtaining a globally unique name without the cost of
+ deploying another registry. However, such use comes with its own
+ costs: domain name ownership may change over time for reasons not
+ anticipated by the URI producer. In other cases, the data within the
+ host component identifies a registered name that has nothing to do
+ with an Internet host. We use the name "host" for the ABNF rule
+ because that is its most common purpose, not its only purpose.
+
+ host = IP-literal / IPv4address / reg-name
+
+ The syntax rule for host is ambiguous because it does not completely
+ distinguish between an IPv4address and a reg-name. In order to
+ disambiguate the syntax, we apply the "first-match-wins" algorithm:
+ If host matches the rule for IPv4address, then it should be
+ considered an IPv4 address literal and not a reg-name. Although host
+ is case-insensitive, producers and normalizers should use lowercase
+ for registered names and hexadecimal addresses for the sake of
+ uniformity, while only using uppercase letters for percent-encodings.
+
+ A host identified by an Internet Protocol literal address, version 6
+ [RFC3513] or later, is distinguished by enclosing the IP literal
+ within square brackets ("[" and "]"). This is the only place where
+ square bracket characters are allowed in the URI syntax. In
+ anticipation of future, as-yet-undefined IP literal address formats,
+ an implementation may use an optional version flag to indicate such a
+ format explicitly rather than rely on heuristic determination.
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ The version flag does not indicate the IP version; rather, it
+ indicates future versions of the literal format. As such,
+ implementations must not provide the version flag for the existing
+ IPv4 and IPv6 literal address forms described below. If a URI
+ containing an IP-literal that starts with "v" (case-insensitive),
+ indicating that the version flag is present, is dereferenced by an
+ application that does not know the meaning of that version flag, then
+ the application should return an appropriate error for "address
+ mechanism not supported".
+
+ A host identified by an IPv6 literal address is represented inside
+ the square brackets without a preceding version flag. The ABNF
+ provided here is a translation of the text definition of an IPv6
+ literal address provided in [RFC3513]. This syntax does not support
+ IPv6 scoped addressing zone identifiers.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 19]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A 128-bit IPv6 address is divided into eight 16-bit pieces. Each
+ piece is represented numerically in case-insensitive hexadecimal,
+ using one to four hexadecimal digits (leading zeroes are permitted).
+ The eight encoded pieces are given most-significant first, separated
+ by colon characters. Optionally, the least-significant two pieces
+ may instead be represented in IPv4 address textual format. A
+ sequence of one or more consecutive zero-valued 16-bit pieces within
+ the address may be elided, omitting all their digits and leaving
+ exactly two consecutive colons in their place to mark the elision.
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ ; least-significant 32 bits of address
+
+ h16 = 1*4HEXDIG
+ ; 16 bits of address represented in hexadecimal
+
+ A host identified by an IPv4 literal address is represented in
+ dotted-decimal notation (a sequence of four decimal numbers in the
+ range 0 to 255, separated by "."), as described in [RFC1123] by
+ reference to [RFC0952]. Note that other forms of dotted notation may
+ be interpreted on some platforms, as described in Section 7.4, but
+ only the dotted-decimal form of four octets is allowed by this
+ grammar.
+
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ A host identified by a registered name is a sequence of characters
+ usually intended for lookup within a locally defined host or service
+ name registry, though the URI's scheme-specific semantics may require
+ that a specific registry (or fixed name table) be used instead. The
+ most common name registry mechanism is the Domain Name System (DNS).
+ A registered name intended for lookup in the DNS uses the syntax
+
+
+
+Berners-Lee, et al. Standards Track [Page 20]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ defined in Section 3.5 of [RFC1034] and Section 2.1 of [RFC1123].
+ Such a name consists of a sequence of domain labels separated by ".",
+ each domain label starting and ending with an alphanumeric character
+ and possibly also containing "-" characters. The rightmost domain
+ label of a fully qualified domain name in DNS may be followed by a
+ single "." and should be if it is necessary to distinguish between
+ the complete domain name and some local domain.
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ If the URI scheme defines a default for host, then that default
+ applies when the host subcomponent is undefined or when the
+ registered name is empty (zero length). For example, the "file" URI
+ scheme is defined so that no authority, an empty host, and
+ "localhost" all mean the end-user's machine, whereas the "http"
+ scheme considers a missing authority or empty host invalid.
+
+ This specification does not mandate a particular registered name
+ lookup technology and therefore does not restrict the syntax of reg-
+ name beyond what is necessary for interoperability. Instead, it
+ delegates the issue of registered name syntax conformance to the
+ operating system of each application performing URI resolution, and
+ that operating system decides what it will allow for the purpose of
+ host identification. A URI resolution implementation might use DNS,
+ host tables, yellow pages, NetInfo, WINS, or any other system for
+ lookup of registered names. However, a globally scoped naming
+ system, such as DNS fully qualified domain names, is necessary for
+ URIs intended to have global scope. URI producers should use names
+ that conform to the DNS syntax, even when use of DNS is not
+ immediately apparent, and should limit these names to no more than
+ 255 characters in length.
+
+ The reg-name syntax allows percent-encoded octets in order to
+ represent non-ASCII registered names in a uniform way that is
+ independent of the underlying name resolution technology. Non-ASCII
+ characters must first be encoded according to UTF-8 [STD63], and then
+ each octet of the corresponding UTF-8 sequence must be percent-
+ encoded to be represented as URI characters. URI producing
+ applications must not use percent-encoding in host unless it is used
+ to represent a UTF-8 character sequence. When a non-ASCII registered
+ name represents an internationalized domain name intended for
+ resolution via the DNS, the name must be transformed to the IDNA
+ encoding [RFC3490] prior to name lookup. URI producers should
+ provide these registered names in the IDNA encoding, rather than a
+ percent-encoding, if they wish to maximize interoperability with
+ legacy URI resolvers.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 21]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+3.2.3. Port
+
+ The port subcomponent of authority is designated by an optional port
+ number in decimal following the host and delimited from it by a
+ single colon (":") character.
+
+ port = *DIGIT
+
+ A scheme may define a default port. For example, the "http" scheme
+ defines a default port of "80", corresponding to its reserved TCP
+ port number. The type of port designated by the port number (e.g.,
+ TCP, UDP, SCTP) is defined by the URI scheme. URI producers and
+ normalizers should omit the port component and its ":" delimiter if
+ port is empty or if its value would be the same as that of the
+ scheme's default.
+
+3.3. Path
+
+ The path component contains data, usually organized in hierarchical
+ form, that, along with data in the non-hierarchical query component
+ (Section 3.4), serves to identify a resource within the scope of the
+ URI's scheme and naming authority (if any). The path is terminated
+ by the first question mark ("?") or number sign ("#") character, or
+ by the end of the URI.
+
+ If a URI contains an authority component, then the path component
+ must either be empty or begin with a slash ("/") character. If a URI
+ does not contain an authority component, then the path cannot begin
+ with two slash characters ("//"). In addition, a URI reference
+ (Section 4.1) may be a relative-path reference, in which case the
+ first path segment cannot contain a colon (":") character. The ABNF
+ requires five separate rules to disambiguate these cases, only one of
+ which will match the path substring within a given URI reference. We
+ use the generic term "path component" to describe the URI substring
+ matched by the parser to one of these rules.
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 22]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ A path consists of a sequence of path segments separated by a slash
+ ("/") character. A path is always defined for a URI, though the
+ defined path may be empty (zero length). Use of the slash character
+ to indicate hierarchy is only required when a URI will be used as the
+ context for relative references. For example, the URI
+ <mailto:fred@example.com> has a path of "fred@example.com", whereas
+ the URI <foo://info.example.com?fred> has an empty path.
+
+ The path segments "." and "..", also known as dot-segments, are
+ defined for relative reference within the path name hierarchy. They
+ are intended for use at the beginning of a relative-path reference
+ (Section 4.2) to indicate relative position within the hierarchical
+ tree of names. This is similar to their role within some operating
+ systems' file directory structures to indicate the current directory
+ and parent directory, respectively. However, unlike in a file
+ system, these dot-segments are only interpreted within the URI path
+ hierarchy and are removed as part of the resolution process (Section
+ 5.2).
+
+ Aside from dot-segments in hierarchical paths, a path segment is
+ considered opaque by the generic syntax. URI producing applications
+ often use the reserved characters allowed in a segment to delimit
+ scheme-specific or dereference-handler-specific subcomponents. For
+ example, the semicolon (";") and equals ("=") reserved characters are
+ often used to delimit parameters and parameter values applicable to
+ that segment. The comma (",") reserved character is often used for
+ similar purposes. For example, one URI producer might use a segment
+ such as "name;v=1.1" to indicate a reference to version 1.1 of
+ "name", whereas another might use a segment such as "name,1.1" to
+ indicate the same. Parameter types may be defined by scheme-specific
+ semantics, but in most cases the syntax of a parameter is specific to
+ the implementation of the URI's dereferencing algorithm.
+
+3.4. Query
+
+ The query component contains non-hierarchical data that, along with
+ data in the path component (Section 3.3), serves to identify a
+ resource within the scope of the URI's scheme and naming authority
+ (if any). The query component is indicated by the first question
+ mark ("?") character and terminated by a number sign ("#") character
+ or by the end of the URI.
+
+
+
+Berners-Lee, et al. Standards Track [Page 23]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ query = *( pchar / "/" / "?" )
+
+ The characters slash ("/") and question mark ("?") may represent data
+ within the query component. Beware that some older, erroneous
+ implementations may not handle such data correctly when it is used as
+ the base URI for relative references (Section 5.1), apparently
+ because they fail to distinguish query data from path data when
+ looking for hierarchical separators. However, as query components
+ are often used to carry identifying information in the form of
+ "key=value" pairs and one frequently used value is a reference to
+ another URI, it is sometimes better for usability to avoid percent-
+ encoding those characters.
+
+3.5. Fragment
+
+ The fragment identifier component of a URI allows indirect
+ identification of a secondary resource by reference to a primary
+ resource and additional identifying information. The identified
+ secondary resource may be some portion or subset of the primary
+ resource, some view on representations of the primary resource, or
+ some other resource defined or described by those representations. A
+ fragment identifier component is indicated by the presence of a
+ number sign ("#") character and terminated by the end of the URI.
+
+ fragment = *( pchar / "/" / "?" )
+
+ The semantics of a fragment identifier are defined by the set of
+ representations that might result from a retrieval action on the
+ primary resource. The fragment's format and resolution is therefore
+ dependent on the media type [RFC2046] of a potentially retrieved
+ representation, even though such a retrieval is only performed if the
+ URI is dereferenced. If no such representation exists, then the
+ semantics of the fragment are considered unknown and are effectively
+ unconstrained. Fragment identifier semantics are independent of the
+ URI scheme and thus cannot be redefined by scheme specifications.
+
+ Individual media types may define their own restrictions on or
+ structures within the fragment identifier syntax for specifying
+ different types of subsets, views, or external references that are
+ identifiable as secondary resources by that media type. If the
+ primary resource has multiple representations, as is often the case
+ for resources whose representation is selected based on attributes of
+ the retrieval request (a.k.a., content negotiation), then whatever is
+ identified by the fragment should be consistent across all of those
+ representations. Each representation should either define the
+ fragment so that it corresponds to the same secondary resource,
+ regardless of how it is represented, or should leave the fragment
+ undefined (i.e., not found).
+
+
+
+Berners-Lee, et al. Standards Track [Page 24]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ As with any URI, use of a fragment identifier component does not
+ imply that a retrieval action will take place. A URI with a fragment
+ identifier may be used to refer to the secondary resource without any
+ implication that the primary resource is accessible or will ever be
+ accessed.
+
+ Fragment identifiers have a special role in information retrieval
+ systems as the primary form of client-side indirect referencing,
+ allowing an author to specifically identify aspects of an existing
+ resource that are only indirectly provided by the resource owner. As
+ such, the fragment identifier is not used in the scheme-specific
+ processing of a URI; instead, the fragment identifier is separated
+ from the rest of the URI prior to a dereference, and thus the
+ identifying information within the fragment itself is dereferenced
+ solely by the user agent, regardless of the URI scheme. Although
+ this separate handling is often perceived to be a loss of
+ information, particularly for accurate redirection of references as
+ resources move over time, it also serves to prevent information
+ providers from denying reference authors the right to refer to
+ information within a resource selectively. Indirect referencing also
+ provides additional flexibility and extensibility to systems that use
+ URIs, as new media types are easier to define and deploy than new
+ schemes of identification.
+
+ The characters slash ("/") and question mark ("?") are allowed to
+ represent data within the fragment identifier. Beware that some
+ older, erroneous implementations may not handle this data correctly
+ when it is used as the base URI for relative references (Section
+ 5.1).
+
+4. Usage
+
+ When applications make reference to a URI, they do not always use the
+ full form of reference defined by the "URI" syntax rule. To save
+ space and take advantage of hierarchical locality, many Internet
+ protocol elements and media type formats allow an abbreviation of a
+ URI, whereas others restrict the syntax to a particular form of URI.
+ We define the most common forms of reference syntax in this
+ specification because they impact and depend upon the design of the
+ generic syntax, requiring a uniform parsing algorithm in order to be
+ interpreted consistently.
+
+4.1. URI Reference
+
+ URI-reference is used to denote the most common usage of a resource
+ identifier.
+
+ URI-reference = URI / relative-ref
+
+
+
+Berners-Lee, et al. Standards Track [Page 25]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A URI-reference is either a URI or a relative reference. If the
+ URI-reference's prefix does not match the syntax of a scheme followed
+ by its colon separator, then the URI-reference is a relative
+ reference.
+
+ A URI-reference is typically parsed first into the five URI
+ components, in order to determine what components are present and
+ whether the reference is relative. Then, each component is parsed
+ for its subparts and their validation. The ABNF of URI-reference,
+ along with the "first-match-wins" disambiguation rule, is sufficient
+ to define a validating parser for the generic syntax. Readers
+ familiar with regular expressions should see Appendix B for an
+ example of a non-validating URI-reference parser that will take any
+ given string and extract the URI components.
+
+4.2. Relative Reference
+
+ A relative reference takes advantage of the hierarchical syntax
+ (Section 1.2.3) to express a URI reference relative to the name space
+ of another hierarchical URI.
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ The URI referred to by a relative reference, also known as the target
+ URI, is obtained by applying the reference resolution algorithm of
+ Section 5.
+
+ A relative reference that begins with two slash characters is termed
+ a network-path reference; such references are rarely used. A
+ relative reference that begins with a single slash character is
+ termed an absolute-path reference. A relative reference that does
+ not begin with a slash character is termed a relative-path reference.
+
+ A path segment that contains a colon character (e.g., "this:that")
+ cannot be used as the first segment of a relative-path reference, as
+ it would be mistaken for a scheme name. Such a segment must be
+ preceded by a dot-segment (e.g., "./this:that") to make a relative-
+ path reference.
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 26]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+4.3. Absolute URI
+
+ Some protocol elements allow only the absolute form of a URI without
+ a fragment identifier. For example, defining a base URI for later
+ use by relative references calls for an absolute-URI syntax rule that
+ does not allow a fragment.
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ URI scheme specifications must define their own syntax so that all
+ strings matching their scheme-specific syntax will also match the
+ <absolute-URI> grammar. Scheme specifications will not define
+ fragment identifier syntax or usage, regardless of its applicability
+ to resources identifiable via that scheme, as fragment identification
+ is orthogonal to scheme definition. However, scheme specifications
+ are encouraged to include a wide range of examples, including
+ examples that show use of the scheme's URIs with fragment identifiers
+ when such usage is appropriate.
+
+4.4. Same-Document Reference
+
+ When a URI reference refers to a URI that is, aside from its fragment
+ component (if any), identical to the base URI (Section 5.1), that
+ reference is called a "same-document" reference. The most frequent
+ examples of same-document references are relative references that are
+ empty or include only the number sign ("#") separator followed by a
+ fragment identifier.
+
+ When a same-document reference is dereferenced for a retrieval
+ action, the target of that reference is defined to be within the same
+ entity (representation, document, or message) as the reference;
+ therefore, a dereference should not result in a new retrieval action.
+
+ Normalization of the base and target URIs prior to their comparison,
+ as described in Sections 6.2.2 and 6.2.3, is allowed but rarely
+ performed in practice. Normalization may increase the set of same-
+ document references, which may be of benefit to some caching
+ applications. As such, reference authors should not assume that a
+ slightly different, though equivalent, reference URI will (or will
+ not) be interpreted as a same-document reference by any given
+ application.
+
+4.5. Suffix Reference
+
+ The URI syntax is designed for unambiguous reference to resources and
+ extensibility via the URI scheme. However, as URI identification and
+ usage have become commonplace, traditional media (television, radio,
+ newspapers, billboards, etc.) have increasingly used a suffix of the
+
+
+
+Berners-Lee, et al. Standards Track [Page 27]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ URI as a reference, consisting of only the authority and path
+ portions of the URI, such as
+
+ www.w3.org/Addressing/
+
+ or simply a DNS registered name on its own. Such references are
+ primarily intended for human interpretation rather than for machines,
+ with the assumption that context-based heuristics are sufficient to
+ complete the URI (e.g., most registered names beginning with "www"
+ are likely to have a URI prefix of "http://"). Although there is no
+ standard set of heuristics for disambiguating a URI suffix, many
+ client implementations allow them to be entered by the user and
+ heuristically resolved.
+
+ Although this practice of using suffix references is common, it
+ should be avoided whenever possible and should never be used in
+ situations where long-term references are expected. The heuristics
+ noted above will change over time, particularly when a new URI scheme
+ becomes popular, and are often incorrect when used out of context.
+ Furthermore, they can lead to security issues along the lines of
+ those described in [RFC1535].
+
+ As a URI suffix has the same syntax as a relative-path reference, a
+ suffix reference cannot be used in contexts where a relative
+ reference is expected. As a result, suffix references are limited to
+ places where there is no defined base URI, such as dialog boxes and
+ off-line advertisements.
+
+5. Reference Resolution
+
+ This section defines the process of resolving a URI reference within
+ a context that allows relative references so that the result is a
+ string matching the <URI> syntax rule of Section 3.
+
+5.1. Establishing a Base URI
+
+ The term "relative" implies that a "base URI" exists against which
+ the relative reference is applied. Aside from fragment-only
+ references (Section 4.4), relative references are only usable when a
+ base URI is known. A base URI must be established by the parser
+ prior to parsing URI references that might be relative. A base URI
+ must conform to the <absolute-URI> syntax rule (Section 4.3). If the
+ base URI is obtained from a URI reference, then that reference must
+ be converted to absolute form and stripped of any fragment component
+ prior to its use as a base URI.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 28]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ The base URI of a reference can be established in one of four ways,
+ discussed below in order of precedence. The order of precedence can
+ be thought of in terms of layers, where the innermost defined base
+ URI has the highest precedence. This can be visualized graphically
+ as follows:
+
+ .----------------------------------------------------------.
+ | .----------------------------------------------------. |
+ | | .----------------------------------------------. | |
+ | | | .----------------------------------------. | | |
+ | | | | .----------------------------------. | | | |
+ | | | | | <relative-reference> | | | | |
+ | | | | `----------------------------------' | | | |
+ | | | | (5.1.1) Base URI embedded in content | | | |
+ | | | `----------------------------------------' | | |
+ | | | (5.1.2) Base URI of the encapsulating entity | | |
+ | | | (message, representation, or none) | | |
+ | | `----------------------------------------------' | |
+ | | (5.1.3) URI used to retrieve the entity | |
+ | `----------------------------------------------------' |
+ | (5.1.4) Default Base URI (application-dependent) |
+ `----------------------------------------------------------'
+
+5.1.1. Base URI Embedded in Content
+
+ Within certain media types, a base URI for relative references can be
+ embedded within the content itself so that it can be readily obtained
+ by a parser. This can be useful for descriptive documents, such as
+ tables of contents, which may be transmitted to others through
+ protocols other than their usual retrieval context (e.g., email or
+ USENET news).
+
+ It is beyond the scope of this specification to specify how, for each
+ media type, a base URI can be embedded. The appropriate syntax, when
+ available, is described by the data format specification associated
+ with each media type.
+
+5.1.2. Base URI from the Encapsulating Entity
+
+ If no base URI is embedded, the base URI is defined by the
+ representation's retrieval context. For a document that is enclosed
+ within another entity, such as a message or archive, the retrieval
+ context is that entity. Thus, the default base URI of a
+ representation is the base URI of the entity in which the
+ representation is encapsulated.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 29]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ A mechanism for embedding a base URI within MIME container types
+ (e.g., the message and multipart types) is defined by MHTML
+ [RFC2557]. Protocols that do not use the MIME message header syntax,
+ but that do allow some form of tagged metadata to be included within
+ messages, may define their own syntax for defining a base URI as part
+ of a message.
+
+5.1.3. Base URI from the Retrieval URI
+
+ If no base URI is embedded and the representation is not encapsulated
+ within some other entity, then, if a URI was used to retrieve the
+ representation, that URI shall be considered the base URI. Note that
+ if the retrieval was the result of a redirected request, the last URI
+ used (i.e., the URI that resulted in the actual retrieval of the
+ representation) is the base URI.
+
+5.1.4. Default Base URI
+
+ If none of the conditions described above apply, then the base URI is
+ defined by the context of the application. As this definition is
+ necessarily application-dependent, failing to define a base URI by
+ using one of the other methods may result in the same content being
+ interpreted differently by different types of applications.
+
+ A sender of a representation containing relative references is
+ responsible for ensuring that a base URI for those references can be
+ established. Aside from fragment-only references, relative
+ references can only be used reliably in situations where the base URI
+ is well defined.
+
+5.2. Relative Resolution
+
+ This section describes an algorithm for converting a URI reference
+ that might be relative to a given base URI into the parsed components
+ of the reference's target. The components can then be recomposed, as
+ described in Section 5.3, to form the target URI. This algorithm
+ provides definitive results that can be used to test the output of
+ other implementations. Applications may implement relative reference
+ resolution by using some other algorithm, provided that the results
+ match what would be given by this one.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 30]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.2.1. Pre-parse the Base URI
+
+ The base URI (Base) is established according to the procedure of
+ Section 5.1 and parsed into the five main components described in
+ Section 3. Note that only the scheme component is required to be
+ present in a base URI; the other components may be empty or
+ undefined. A component is undefined if its associated delimiter does
+ not appear in the URI reference; the path component is never
+ undefined, though it may be empty.
+
+ Normalization of the base URI, as described in Sections 6.2.2 and
+ 6.2.3, is optional. A URI reference must be transformed to its
+ target URI before it can be normalized.
+
+5.2.2. Transform References
+
+ For each URI reference (R), the following pseudocode describes an
+ algorithm for transforming R into its target URI (T):
+
+ -- The URI reference is parsed into the five URI components
+ --
+ (R.scheme, R.authority, R.path, R.query, R.fragment) = parse(R);
+
+ -- A non-strict parser may ignore a scheme in the reference
+ -- if it is identical to the base URI's scheme.
+ --
+ if ((not strict) and (R.scheme == Base.scheme)) then
+ undefine(R.scheme);
+ endif;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 31]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ if defined(R.scheme) then
+ T.scheme = R.scheme;
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if defined(R.authority) then
+ T.authority = R.authority;
+ T.path = remove_dot_segments(R.path);
+ T.query = R.query;
+ else
+ if (R.path == "") then
+ T.path = Base.path;
+ if defined(R.query) then
+ T.query = R.query;
+ else
+ T.query = Base.query;
+ endif;
+ else
+ if (R.path starts-with "/") then
+ T.path = remove_dot_segments(R.path);
+ else
+ T.path = merge(Base.path, R.path);
+ T.path = remove_dot_segments(T.path);
+ endif;
+ T.query = R.query;
+ endif;
+ T.authority = Base.authority;
+ endif;
+ T.scheme = Base.scheme;
+ endif;
+
+ T.fragment = R.fragment;
+
+5.2.3. Merge Paths
+
+ The pseudocode above refers to a "merge" routine for merging a
+ relative-path reference with the path of the base URI. This is
+ accomplished as follows:
+
+ o If the base URI has a defined authority component and an empty
+ path, then return a string consisting of "/" concatenated with the
+ reference's path; otherwise,
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 32]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o return a string consisting of the reference's path component
+ appended to all but the last segment of the base URI's path (i.e.,
+ excluding any characters after the right-most "/" in the base URI
+ path, or excluding the entire base URI path if it does not contain
+ any "/" characters).
+
+5.2.4. Remove Dot Segments
+
+ The pseudocode also refers to a "remove_dot_segments" routine for
+ interpreting and removing the special "." and ".." complete path
+ segments from a referenced path. This is done after the path is
+ extracted from a reference, whether or not the path was relative, in
+ order to remove any invalid or extraneous dot-segments prior to
+ forming the target URI. Although there are many ways to accomplish
+ this removal process, we describe a simple method using two string
+ buffers.
+
+ 1. The input buffer is initialized with the now-appended path
+ components and the output buffer is initialized to the empty
+ string.
+
+ 2. While the input buffer is not empty, loop as follows:
+
+ A. If the input buffer begins with a prefix of "../" or "./",
+ then remove that prefix from the input buffer; otherwise,
+
+ B. if the input buffer begins with a prefix of "/./" or "/.",
+ where "." is a complete path segment, then replace that
+ prefix with "/" in the input buffer; otherwise,
+
+ C. if the input buffer begins with a prefix of "/../" or "/..",
+ where ".." is a complete path segment, then replace that
+ prefix with "/" in the input buffer and remove the last
+ segment and its preceding "/" (if any) from the output
+ buffer; otherwise,
+
+ D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise,
+
+ E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if
+ any) and any subsequent characters up to, but not including,
+ the next "/" character or the end of the input buffer.
+
+ 3. Finally, the output buffer is returned as the result of
+ remove_dot_segments.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 33]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Note that dot-segments are intended for use in URI references to
+ express an identifier relative to the hierarchy of names in the base
+ URI. The remove_dot_segments algorithm respects that hierarchy by
+ removing extra dot-segments rather than treat them as an error or
+ leaving them to be misinterpreted by dereference implementations.
+
+ The following illustrates how the above steps are applied for two
+ examples of merged paths, showing the state of the two buffers after
+ each step.
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : /a/b/c/./../../g
+ 2E: /a /b/c/./../../g
+ 2E: /a/b /c/./../../g
+ 2E: /a/b/c /./../../g
+ 2B: /a/b/c /../../g
+ 2C: /a/b /../g
+ 2C: /a /g
+ 2E: /a/g
+
+ STEP OUTPUT BUFFER INPUT BUFFER
+
+ 1 : mid/content=5/../6
+ 2E: mid /content=5/../6
+ 2E: mid/content=5 /../6
+ 2C: mid /6
+ 2E: mid/6
+
+ Some applications may find it more efficient to implement the
+ remove_dot_segments algorithm by using two segment stacks rather than
+ strings.
+
+ Note: Beware that some older, erroneous implementations will fail
+ to separate a reference's query component from its path component
+ prior to merging the base and reference paths, resulting in an
+ interoperability failure if the query component contains the
+ strings "/../" or "/./".
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 34]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.3. Component Recomposition
+
+ Parsed URI components can be recomposed to obtain the corresponding
+ URI reference string. Using pseudocode, this would be:
+
+ result = ""
+
+ if defined(scheme) then
+ append scheme to result;
+ append ":" to result;
+ endif;
+
+ if defined(authority) then
+ append "//" to result;
+ append authority to result;
+ endif;
+
+ append path to result;
+
+ if defined(query) then
+ append "?" to result;
+ append query to result;
+ endif;
+
+ if defined(fragment) then
+ append "#" to result;
+ append fragment to result;
+ endif;
+
+ return result;
+
+ Note that we are careful to preserve the distinction between a
+ component that is undefined, meaning that its separator was not
+ present in the reference, and a component that is empty, meaning that
+ the separator was present and was immediately followed by the next
+ component separator or the end of the reference.
+
+5.4. Reference Resolution Examples
+
+ Within a representation with a well defined base URI of
+
+ http://a/b/c/d;p?q
+
+ a relative reference is transformed to its target URI as follows.
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 35]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+5.4.1. Normal Examples
+
+ "g:h" = "g:h"
+ "g" = "http://a/b/c/g"
+ "./g" = "http://a/b/c/g"
+ "g/" = "http://a/b/c/g/"
+ "/g" = "http://a/g"
+ "//g" = "http://g"
+ "?y" = "http://a/b/c/d;p?y"
+ "g?y" = "http://a/b/c/g?y"
+ "#s" = "http://a/b/c/d;p?q#s"
+ "g#s" = "http://a/b/c/g#s"
+ "g?y#s" = "http://a/b/c/g?y#s"
+ ";x" = "http://a/b/c/;x"
+ "g;x" = "http://a/b/c/g;x"
+ "g;x?y#s" = "http://a/b/c/g;x?y#s"
+ "" = "http://a/b/c/d;p?q"
+ "." = "http://a/b/c/"
+ "./" = "http://a/b/c/"
+ ".." = "http://a/b/"
+ "../" = "http://a/b/"
+ "../g" = "http://a/b/g"
+ "../.." = "http://a/"
+ "../../" = "http://a/"
+ "../../g" = "http://a/g"
+
+5.4.2. Abnormal Examples
+
+ Although the following abnormal examples are unlikely to occur in
+ normal practice, all URI parsers should be capable of resolving them
+ consistently. Each example uses the same base as that above.
+
+ Parsers must be careful in handling cases where there are more ".."
+ segments in a relative-path reference than there are hierarchical
+ levels in the base URI's path. Note that the ".." syntax cannot be
+ used to change the authority component of a URI.
+
+ "../../../g" = "http://a/g"
+ "../../../../g" = "http://a/g"
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 36]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Similarly, parsers must remove the dot-segments "." and ".." when
+ they are complete components of a path, but not when they are only
+ part of a segment.
+
+ "/./g" = "http://a/g"
+ "/../g" = "http://a/g"
+ "g." = "http://a/b/c/g."
+ ".g" = "http://a/b/c/.g"
+ "g.." = "http://a/b/c/g.."
+ "..g" = "http://a/b/c/..g"
+
+ Less likely are cases where the relative reference uses unnecessary
+ or nonsensical forms of the "." and ".." complete path segments.
+
+ "./../g" = "http://a/b/g"
+ "./g/." = "http://a/b/c/g/"
+ "g/./h" = "http://a/b/c/g/h"
+ "g/../h" = "http://a/b/c/h"
+ "g;x=1/./y" = "http://a/b/c/g;x=1/y"
+ "g;x=1/../y" = "http://a/b/c/y"
+
+ Some applications fail to separate the reference's query and/or
+ fragment components from the path component before merging it with
+ the base path and removing dot-segments. This error is rarely
+ noticed, as typical usage of a fragment never includes the hierarchy
+ ("/") character and the query component is not normally used within
+ relative references.
+
+ "g?y/./x" = "http://a/b/c/g?y/./x"
+ "g?y/../x" = "http://a/b/c/g?y/../x"
+ "g#s/./x" = "http://a/b/c/g#s/./x"
+ "g#s/../x" = "http://a/b/c/g#s/../x"
+
+ Some parsers allow the scheme name to be present in a relative
+ reference if it is the same as the base URI scheme. This is
+ considered to be a loophole in prior specifications of partial URI
+ [RFC1630]. Its use should be avoided but is allowed for backward
+ compatibility.
+
+ "http:g" = "http:g" ; for strict parsers
+ / "http://a/b/c/g" ; for backward compatibility
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 37]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6. Normalization and Comparison
+
+ One of the most common operations on URIs is simple comparison:
+ determining whether two URIs are equivalent without using the URIs to
+ access their respective resource(s). A comparison is performed every
+ time a response cache is accessed, a browser checks its history to
+ color a link, or an XML parser processes tags within a namespace.
+ Extensive normalization prior to comparison of URIs is often used by
+ spiders and indexing engines to prune a search space or to reduce
+ duplication of request actions and response storage.
+
+ URI comparison is performed for some particular purpose. Protocols
+ or implementations that compare URIs for different purposes will
+ often be subject to differing design trade-offs in regards to how
+ much effort should be spent in reducing aliased identifiers. This
+ section describes various methods that may be used to compare URIs,
+ the trade-offs between them, and the types of applications that might
+ use them.
+
+6.1. Equivalence
+
+ Because URIs exist to identify resources, presumably they should be
+ considered equivalent when they identify the same resource. However,
+ this definition of equivalence is not of much practical use, as there
+ is no way for an implementation to compare two resources unless it
+ has full knowledge or control of them. For this reason,
+ determination of equivalence or difference of URIs is based on string
+ comparison, perhaps augmented by reference to additional rules
+ provided by URI scheme definitions. We use the terms "different" and
+ "equivalent" to describe the possible outcomes of such comparisons,
+ but there are many application-dependent versions of equivalence.
+
+ Even though it is possible to determine that two URIs are equivalent,
+ URI comparison is not sufficient to determine whether two URIs
+ identify different resources. For example, an owner of two different
+ domain names could decide to serve the same resource from both,
+ resulting in two different URIs. Therefore, comparison methods are
+ designed to minimize false negatives while strictly avoiding false
+ positives.
+
+ In testing for equivalence, applications should not directly compare
+ relative references; the references should be converted to their
+ respective target URIs before comparison. When URIs are compared to
+ select (or avoid) a network action, such as retrieval of a
+ representation, fragment components (if any) should be excluded from
+ the comparison.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 38]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2. Comparison Ladder
+
+ A variety of methods are used in practice to test URI equivalence.
+ These methods fall into a range, distinguished by the amount of
+ processing required and the degree to which the probability of false
+ negatives is reduced. As noted above, false negatives cannot be
+ eliminated. In practice, their probability can be reduced, but this
+ reduction requires more processing and is not cost-effective for all
+ applications.
+
+ If this range of comparison practices is considered as a ladder, the
+ following discussion will climb the ladder, starting with practices
+ that are cheap but have a relatively higher chance of producing false
+ negatives, and proceeding to those that have higher computational
+ cost and lower risk of false negatives.
+
+6.2.1. Simple String Comparison
+
+ If two URIs, when considered as character strings, are identical,
+ then it is safe to conclude that they are equivalent. This type of
+ equivalence test has very low computational cost and is in wide use
+ in a variety of applications, particularly in the domain of parsing.
+
+ Testing strings for equivalence requires some basic precautions.
+ This procedure is often referred to as "bit-for-bit" or
+ "byte-for-byte" comparison, which is potentially misleading. Testing
+ strings for equality is normally based on pair comparison of the
+ characters that make up the strings, starting from the first and
+ proceeding until both strings are exhausted and all characters are
+ found to be equal, until a pair of characters compares unequal, or
+ until one of the strings is exhausted before the other.
+
+ This character comparison requires that each pair of characters be
+ put in comparable form. For example, should one URI be stored in a
+ byte array in EBCDIC encoding and the second in a Java String object
+ (UTF-16), bit-for-bit comparisons applied naively will produce
+ errors. It is better to speak of equality on a character-for-
+ character basis rather than on a byte-for-byte or bit-for-bit basis.
+ In practical terms, character-by-character comparisons should be done
+ codepoint-by-codepoint after conversion to a common character
+ encoding.
+
+ False negatives are caused by the production and use of URI aliases.
+ Unnecessary aliases can be reduced, regardless of the comparison
+ method, by consistently providing URI references in an already-
+ normalized form (i.e., a form identical to what would be produced
+ after normalization is applied, as described below).
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 39]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ Protocols and data formats often limit some URI comparisons to simple
+ string comparison, based on the theory that people and
+ implementations will, in their own best interest, be consistent in
+ providing URI references, or at least consistent enough to negate any
+ efficiency that might be obtained from further normalization.
+
+6.2.2. Syntax-Based Normalization
+
+ Implementations may use logic based on the definitions provided by
+ this specification to reduce the probability of false negatives.
+ This processing is moderately higher in cost than character-for-
+ character string comparison. For example, an application using this
+ approach could reasonably consider the following two URIs equivalent:
+
+ example://a/b/c/%7Bfoo%7D
+ eXAMPLE://a/./b/../b/%63/%7bfoo%7d
+
+ Web user agents, such as browsers, typically apply this type of URI
+ normalization when determining whether a cached response is
+ available. Syntax-based normalization includes such techniques as
+ case normalization, percent-encoding normalization, and removal of
+ dot-segments.
+
+6.2.2.1. Case Normalization
+
+ For all URIs, the hexadecimal digits within a percent-encoding
+ triplet (e.g., "%3a" versus "%3A") are case-insensitive and therefore
+ should be normalized to use uppercase letters for the digits A-F.
+
+ When a URI uses components of the generic syntax, the component
+ syntax equivalence rules always apply; namely, that the scheme and
+ host are case-insensitive and therefore should be normalized to
+ lowercase. For example, the URI <HTTP://www.EXAMPLE.com/> is
+ equivalent to <http://www.example.com/>. The other generic syntax
+ components are assumed to be case-sensitive unless specifically
+ defined otherwise by the scheme (see Section 6.2.3).
+
+6.2.2.2. Percent-Encoding Normalization
+
+ The percent-encoding mechanism (Section 2.1) is a frequent source of
+ variance among otherwise identical URIs. In addition to the case
+ normalization issue noted above, some URI producers percent-encode
+ octets that do not require percent-encoding, resulting in URIs that
+ are equivalent to their non-encoded counterparts. These URIs should
+ be normalized by decoding any percent-encoded octet that corresponds
+ to an unreserved character, as described in Section 2.3.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 40]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+6.2.2.3. Path Segment Normalization
+
+ The complete path segments "." and ".." are intended only for use
+ within relative references (Section 4.1) and are removed as part of
+ the reference resolution process (Section 5.2). However, some
+ deployed implementations incorrectly assume that reference resolution
+ is not necessary when the reference is already a URI and thus fail to
+ remove dot-segments when they occur in non-relative paths. URI
+ normalizers should remove dot-segments by applying the
+ remove_dot_segments algorithm to the path, as described in
+ Section 5.2.4.
+
+6.2.3. Scheme-Based Normalization
+
+ The syntax and semantics of URIs vary from scheme to scheme, as
+ described by the defining specification for each scheme.
+ Implementations may use scheme-specific rules, at further processing
+ cost, to reduce the probability of false negatives. For example,
+ because the "http" scheme makes use of an authority component, has a
+ default port of "80", and defines an empty path to be equivalent to
+ "/", the following four URIs are equivalent:
+
+ http://example.com
+ http://example.com/
+ http://example.com:/
+ http://example.com:80/
+
+ In general, a URI that uses the generic syntax for authority with an
+ empty path should be normalized to a path of "/". Likewise, an
+ explicit ":port", for which the port is empty or the default for the
+ scheme, is equivalent to one where the port and its ":" delimiter are
+ elided and thus should be removed by scheme-based normalization. For
+ example, the second URI above is the normal form for the "http"
+ scheme.
+
+ Another case where normalization varies by scheme is in the handling
+ of an empty authority component or empty host subcomponent. For many
+ scheme specifications, an empty authority or host is considered an
+ error; for others, it is considered equivalent to "localhost" or the
+ end-user's host. When a scheme defines a default for authority and a
+ URI reference to that default is desired, the reference should be
+ normalized to an empty authority for the sake of uniformity, brevity,
+ and internationalization. If, however, either the userinfo or port
+ subcomponents are non-empty, then the host should be given explicitly
+ even if it matches the default.
+
+ Normalization should not remove delimiters when their associated
+ component is empty unless licensed to do so by the scheme
+
+
+
+Berners-Lee, et al. Standards Track [Page 41]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ specification. For example, the URI "http://example.com/?" cannot be
+ assumed to be equivalent to any of the examples above. Likewise, the
+ presence or absence of delimiters within a userinfo subcomponent is
+ usually significant to its interpretation. The fragment component is
+ not subject to any scheme-based normalization; thus, two URIs that
+ differ only by the suffix "#" are considered different regardless of
+ the scheme.
+
+ Some schemes define additional subcomponents that consist of case-
+ insensitive data, giving an implicit license to normalizers to
+ convert this data to a common case (e.g., all lowercase). For
+ example, URI schemes that define a subcomponent of path to contain an
+ Internet hostname, such as the "mailto" URI scheme, cause that
+ subcomponent to be case-insensitive and thus subject to case
+ normalization (e.g., "mailto:Joe@Example.COM" is equivalent to
+ "mailto:Joe@example.com", even though the generic syntax considers
+ the path component to be case-sensitive).
+
+ Other scheme-specific normalizations are possible.
+
+6.2.4. Protocol-Based Normalization
+
+ Substantial effort to reduce the incidence of false negatives is
+ often cost-effective for web spiders. Therefore, they implement even
+ more aggressive techniques in URI comparison. For example, if they
+ observe that a URI such as
+
+ http://example.com/data
+
+ redirects to a URI differing only in the trailing slash
+
+ http://example.com/data/
+
+ they will likely regard the two as equivalent in the future. This
+ kind of technique is only appropriate when equivalence is clearly
+ indicated by both the result of accessing the resources and the
+ common conventions of their scheme's dereference algorithm (in this
+ case, use of redirection by HTTP origin servers to avoid problems
+ with relative references).
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 42]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7. Security Considerations
+
+ A URI does not in itself pose a security threat. However, as URIs
+ are often used to provide a compact set of instructions for access to
+ network resources, care must be taken to properly interpret the data
+ within a URI, to prevent that data from causing unintended access,
+ and to avoid including data that should not be revealed in plain
+ text.
+
+7.1. Reliability and Consistency
+
+ There is no guarantee that once a URI has been used to retrieve
+ information, the same information will be retrievable by that URI in
+ the future. Nor is there any guarantee that the information
+ retrievable via that URI in the future will be observably similar to
+ that retrieved in the past. The URI syntax does not constrain how a
+ given scheme or authority apportions its namespace or maintains it
+ over time. Such guarantees can only be obtained from the person(s)
+ controlling that namespace and the resource in question. A specific
+ URI scheme may define additional semantics, such as name persistence,
+ if those semantics are required of all naming authorities for that
+ scheme.
+
+7.2. Malicious Construction
+
+ It is sometimes possible to construct a URI so that an attempt to
+ perform a seemingly harmless, idempotent operation, such as the
+ retrieval of a representation, will in fact cause a possibly damaging
+ remote operation. The unsafe URI is typically constructed by
+ specifying a port number other than that reserved for the network
+ protocol in question. The client unwittingly contacts a site running
+ a different protocol service, and data within the URI contains
+ instructions that, when interpreted according to this other protocol,
+ cause an unexpected operation. A frequent example of such abuse has
+ been the use of a protocol-based scheme with a port component of
+ "25", thereby fooling user agent software into sending an unintended
+ or impersonating message via an SMTP server.
+
+ Applications should prevent dereference of a URI that specifies a TCP
+ port number within the "well-known port" range (0 - 1023) unless the
+ protocol being used to dereference that URI is compatible with the
+ protocol expected on that well-known port. Although IANA maintains a
+ registry of well-known ports, applications should make such
+ restrictions user-configurable to avoid preventing the deployment of
+ new services.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 43]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ When a URI contains percent-encoded octets that match the delimiters
+ for a given resolution or dereference protocol (for example, CR and
+ LF characters for the TELNET protocol), these percent-encodings must
+ not be decoded before transmission across that protocol. Transfer of
+ the percent-encoding, which might violate the protocol, is less
+ harmful than allowing decoded octets to be interpreted as additional
+ operations or parameters, perhaps triggering an unexpected and
+ possibly harmful remote operation.
+
+7.3. Back-End Transcoding
+
+ When a URI is dereferenced, the data within it is often parsed by
+ both the user agent and one or more servers. In HTTP, for example, a
+ typical user agent will parse a URI into its five major components,
+ access the authority's server, and send it the data within the
+ authority, path, and query components. A typical server will take
+ that information, parse the path into segments and the query into
+ key/value pairs, and then invoke implementation-specific handlers to
+ respond to the request. As a result, a common security concern for
+ server implementations that handle a URI, either as a whole or split
+ into separate components, is proper interpretation of the octet data
+ represented by the characters and percent-encodings within that URI.
+
+ Percent-encoded octets must be decoded at some point during the
+ dereference process. Applications must split the URI into its
+ components and subcomponents prior to decoding the octets, as
+ otherwise the decoded octets might be mistaken for delimiters.
+ Security checks of the data within a URI should be applied after
+ decoding the octets. Note, however, that the "%00" percent-encoding
+ (NUL) may require special handling and should be rejected if the
+ application is not expecting to receive raw data within a component.
+
+ Special care should be taken when the URI path interpretation process
+ involves the use of a back-end file system or related system
+ functions. File systems typically assign an operational meaning to
+ special characters, such as the "/", "\", ":", "[", and "]"
+ characters, and to special device names like ".", "..", "...", "aux",
+ "lpt", etc. In some cases, merely testing for the existence of such
+ a name will cause the operating system to pause or invoke unrelated
+ system calls, leading to significant security concerns regarding
+ denial of service and unintended data transfer. It would be
+ impossible for this specification to list all such significant
+ characters and device names. Implementers should research the
+ reserved names and characters for the types of storage device that
+ may be attached to their applications and restrict the use of data
+ obtained from URI components accordingly.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 44]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+7.4. Rare IP Address Formats
+
+ Although the URI syntax for IPv4address only allows the common
+ dotted-decimal form of IPv4 address literal, many implementations
+ that process URIs make use of platform-dependent system routines,
+ such as gethostbyname() and inet_aton(), to translate the string
+ literal to an actual IP address. Unfortunately, such system routines
+ often allow and process a much larger set of formats than those
+ described in Section 3.2.2.
+
+ For example, many implementations allow dotted forms of three
+ numbers, wherein the last part is interpreted as a 16-bit quantity
+ and placed in the right-most two bytes of the network address (e.g.,
+ a Class B network). Likewise, a dotted form of two numbers means
+ that the last part is interpreted as a 24-bit quantity and placed in
+ the right-most three bytes of the network address (Class A), and a
+ single number (without dots) is interpreted as a 32-bit quantity and
+ stored directly in the network address. Adding further to the
+ confusion, some implementations allow each dotted part to be
+ interpreted as decimal, octal, or hexadecimal, as specified in the C
+ language (i.e., a leading 0x or 0X implies hexadecimal; a leading 0
+ implies octal; otherwise, the number is interpreted as decimal).
+
+ These additional IP address formats are not allowed in the URI syntax
+ due to differences between platform implementations. However, they
+ can become a security concern if an application attempts to filter
+ access to resources based on the IP address in string literal format.
+ If this filtering is performed, literals should be converted to
+ numeric form and filtered based on the numeric value, and not on a
+ prefix or suffix of the string form.
+
+7.5. Sensitive Information
+
+ URI producers should not provide a URI that contains a username or
+ password that is intended to be secret. URIs are frequently
+ displayed by browsers, stored in clear text bookmarks, and logged by
+ user agent history and intermediary applications (proxies). A
+ password appearing within the userinfo component is deprecated and
+ should be considered an error (or simply ignored) except in those
+ rare cases where the 'password' parameter is intended to be public.
+
+7.6. Semantic Attacks
+
+ Because the userinfo subcomponent is rarely used and appears before
+ the host in the authority component, it can be used to construct a
+ URI intended to mislead a human user by appearing to identify one
+ (trusted) naming authority while actually identifying a different
+ authority hidden behind the noise. For example
+
+
+
+Berners-Lee, et al. Standards Track [Page 45]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ftp://cnn.example.com&story=breaking_news@10.0.0.1/top_story.htm
+
+ might lead a human user to assume that the host is 'cnn.example.com',
+ whereas it is actually '10.0.0.1'. Note that a misleading userinfo
+ subcomponent could be much longer than the example above.
+
+ A misleading URI, such as that above, is an attack on the user's
+ preconceived notions about the meaning of a URI rather than an attack
+ on the software itself. User agents may be able to reduce the impact
+ of such attacks by distinguishing the various components of the URI
+ when they are rendered, such as by using a different color or tone to
+ render userinfo if any is present, though there is no panacea. More
+ information on URI-based semantic attacks can be found in [Siedzik].
+
+8. IANA Considerations
+
+ URI scheme names, as defined by <scheme> in Section 3.1, form a
+ registered namespace that is managed by IANA according to the
+ procedures defined in [BCP35]. No IANA actions are required by this
+ document.
+
+9. Acknowledgements
+
+ This specification is derived from RFC 2396 [RFC2396], RFC 1808
+ [RFC1808], and RFC 1738 [RFC1738]; the acknowledgements in those
+ documents still apply. It also incorporates the update (with
+ corrections) for IPv6 literals in the host syntax, as defined by
+ Robert M. Hinden, Brian E. Carpenter, and Larry Masinter in
+ [RFC2732]. In addition, contributions by Gisle Aas, Reese Anschultz,
+ Daniel Barclay, Tim Bray, Mike Brown, Rob Cameron, Jeremy Carroll,
+ Dan Connolly, Adam M. Costello, John Cowan, Jason Diamond, Martin
+ Duerst, Stefan Eissing, Clive D.W. Feather, Al Gilman, Tony Hammond,
+ Elliotte Harold, Pat Hayes, Henry Holtzman, Ian B. Jacobs, Michael
+ Kay, John C. Klensin, Graham Klyne, Dan Kohn, Bruce Lilly, Andrew
+ Main, Dave McAlpin, Ira McDonald, Michael Mealling, Ray Merkert,
+ Stephen Pollei, Julian Reschke, Tomas Rokicki, Miles Sabin, Kai
+ Schaetzl, Mark Thomson, Ronald Tschalaer, Norm Walsh, Marc Warne,
+ Stuart Williams, and Henry Zongaro are gratefully acknowledged.
+
+10. References
+
+10.1. Normative References
+
+ [ASCII] American National Standards Institute, "Coded Character
+ Set -- 7-bit American Standard Code for Information
+ Interchange", ANSI X3.4, 1986.
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 46]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [STD63] Yergeau, F., "UTF-8, a transformation format of
+ ISO 10646", STD 63, RFC 3629, November 2003.
+
+ [UCS] International Organization for Standardization,
+ "Information Technology - Universal Multiple-Octet Coded
+ Character Set (UCS)", ISO/IEC 10646:2003, December 2003.
+
+10.2. Informative References
+
+ [BCP19] Freed, N. and J. Postel, "IANA Charset Registration
+ Procedures", BCP 19, RFC 2978, October 2000.
+
+ [BCP35] Petke, R. and I. King, "Registration Procedures for URL
+ Scheme Names", BCP 35, RFC 2717, November 1999.
+
+ [RFC0952] Harrenstien, K., Stahl, M., and E. Feinler, "DoD Internet
+ host table specification", RFC 952, October 1985.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC1535] Gavron, E., "A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software", RFC 1535,
+ October 1993.
+
+ [RFC1630] Berners-Lee, T., "Universal Resource Identifiers in WWW: A
+ Unifying Syntax for the Expression of Names and Addresses
+ of Objects on the Network as used in the World-Wide Web",
+ RFC 1630, June 1994.
+
+ [RFC1736] Kunze, J., "Functional Recommendations for Internet
+ Resource Locators", RFC 1736, February 1995.
+
+ [RFC1737] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", RFC 1737, December 1994.
+
+ [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators",
+ RFC 1808, June 1995.
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 47]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+ [RFC2141] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [RFC2396] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
+ Jensen, "HTTP Extensions for Distributed Authoring --
+ WEBDAV", RFC 2518, February 1999.
+
+ [RFC2557] Palme, J., Hopmann, A., and N. Shelness, "MIME
+ Encapsulation of Aggregate Documents, such as HTML
+ (MHTML)", RFC 2557, March 1999.
+
+ [RFC2718] Masinter, L., Alvestrand, H., Zigmond, D., and R. Petke,
+ "Guidelines for new URL Schemes", RFC 2718, November 1999.
+
+ [RFC2732] Hinden, R., Carpenter, B., and L. Masinter, "Format for
+ Literal IPv6 Addresses in URL's", RFC 2732, December 1999.
+
+ [RFC3305] Mealling, M. and R. Denenberg, "Report from the Joint
+ W3C/IETF URI Planning Interest Group: Uniform Resource
+ Identifiers (URIs), URLs, and Uniform Resource Names
+ (URNs): Clarifications and Recommendations", RFC 3305,
+ August 2002.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications (IDNA)",
+ RFC 3490, March 2003.
+
+ [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [Siedzik] Siedzik, R., "Semantic Attacks: What's in a URL?",
+ April 2001, <http://www.giac.org/practical/gsec/
+ Richard_Siedzik_GSEC.pdf>.
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 48]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix A. Collected ABNF for URI
+
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+
+ URI-reference = URI / relative-ref
+
+ absolute-URI = scheme ":" hier-part [ "?" query ]
+
+ relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+
+ relative-part = "//" authority path-abempty
+ / path-absolute
+ / path-noscheme
+ / path-empty
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ authority = [ userinfo "@" ] host [ ":" port ]
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ host = IP-literal / IPv4address / reg-name
+ port = *DIGIT
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ h16 = 1*4HEXDIG
+ ls32 = ( h16 ":" h16 ) / IPv4address
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 49]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ reg-name = *( unreserved / pct-encoded / sub-delims )
+
+ path = path-abempty ; begins with "/" or is empty
+ / path-absolute ; begins with "/" but not "//"
+ / path-noscheme ; begins with a non-colon segment
+ / path-rootless ; begins with a segment
+ / path-empty ; zero characters
+
+ path-abempty = *( "/" segment )
+ path-absolute = "/" [ segment-nz *( "/" segment ) ]
+ path-noscheme = segment-nz-nc *( "/" segment )
+ path-rootless = segment-nz *( "/" segment )
+ path-empty = 0<pchar>
+
+ segment = *pchar
+ segment-nz = 1*pchar
+ segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+
+ query = *( pchar / "/" / "?" )
+
+ fragment = *( pchar / "/" / "?" )
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+Appendix B. Parsing a URI Reference with a Regular Expression
+
+ As the "first-match-wins" algorithm is identical to the "greedy"
+ disambiguation method used by POSIX regular expressions, it is
+ natural and commonplace to use a regular expression for parsing the
+ potential five components of a URI reference.
+
+ The following line is the regular expression for breaking-down a
+ well-formed URI reference into its components.
+
+
+
+Berners-Lee, et al. Standards Track [Page 50]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+ 12 3 4 5 6 7 8 9
+
+ The numbers in the second line above are only to assist readability;
+ they indicate the reference points for each subexpression (i.e., each
+ paired parenthesis). We refer to the value matched for subexpression
+ <n> as $<n>. For example, matching the above expression to
+
+ http://www.ics.uci.edu/pub/ietf/uri/#Related
+
+ results in the following subexpression matches:
+
+ $1 = http:
+ $2 = http
+ $3 = //www.ics.uci.edu
+ $4 = www.ics.uci.edu
+ $5 = /pub/ietf/uri/
+ $6 = <undefined>
+ $7 = <undefined>
+ $8 = #Related
+ $9 = Related
+
+ where <undefined> indicates that the component is not present, as is
+ the case for the query component in the above example. Therefore, we
+ can determine the value of the five components as
+
+ scheme = $2
+ authority = $4
+ path = $5
+ query = $7
+ fragment = $9
+
+ Going in the opposite direction, we can recreate a URI reference from
+ its components by using the algorithm of Section 5.3.
+
+Appendix C. Delimiting a URI in Context
+
+ URIs are often transmitted through formats that do not provide a
+ clear context for their interpretation. For example, there are many
+ occasions when a URI is included in plain text; examples include text
+ sent in email, USENET news, and on printed paper. In such cases, it
+ is important to be able to delimit the URI from the rest of the text,
+ and in particular from punctuation marks that might be mistaken for
+ part of the URI.
+
+ In practice, URIs are delimited in a variety of ways, but usually
+ within double-quotes "http://example.com/", angle brackets
+ <http://example.com/>, or just by using whitespace:
+
+
+
+Berners-Lee, et al. Standards Track [Page 51]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ http://example.com/
+
+ These wrappers do not form part of the URI.
+
+ In some cases, extra whitespace (spaces, line-breaks, tabs, etc.) may
+ have to be added to break a long URI across lines. The whitespace
+ should be ignored when the URI is extracted.
+
+ No whitespace should be introduced after a hyphen ("-") character.
+ Because some typesetters and printers may (erroneously) introduce a
+ hyphen at the end of line when breaking it, the interpreter of a URI
+ containing a line break immediately after a hyphen should ignore all
+ whitespace around the line break and should be aware that the hyphen
+ may or may not actually be part of the URI.
+
+ Using <> angle brackets around each URI is especially recommended as
+ a delimiting style for a reference that contains embedded whitespace.
+
+ The prefix "URL:" (with or without a trailing space) was formerly
+ recommended as a way to help distinguish a URI from other bracketed
+ designators, though it is not commonly used in practice and is no
+ longer recommended.
+
+ For robustness, software that accepts user-typed URI should attempt
+ to recognize and strip both delimiters and embedded whitespace.
+
+ For example, the text
+
+ Yes, Jim, I found it under "http://www.w3.org/Addressing/",
+ but you can probably pick it up from <ftp://foo.example.
+ com/rfc/>. Note the warning in <http://www.ics.uci.edu/pub/
+ ietf/uri/historical.html#WARNING>.
+
+ contains the URI references
+
+ http://www.w3.org/Addressing/
+ ftp://foo.example.com/rfc/
+ http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 52]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Appendix D. Changes from RFC 2396
+
+D.1. Additions
+
+ An ABNF rule for URI has been introduced to correspond to one common
+ usage of the term: an absolute URI with optional fragment.
+
+ IPv6 (and later) literals have been added to the list of possible
+ identifiers for the host portion of an authority component, as
+ described by [RFC2732], with the addition of "[" and "]" to the
+ reserved set and a version flag to anticipate future versions of IP
+ literals. Square brackets are now specified as reserved within the
+ authority component and are not allowed outside their use as
+ delimiters for an IP literal within host. In order to make this
+ change without changing the technical definition of the path, query,
+ and fragment components, those rules were redefined to directly
+ specify the characters allowed.
+
+ As [RFC2732] defers to [RFC3513] for definition of an IPv6 literal
+ address, which, unfortunately, lacks an ABNF description of
+ IPv6address, we created a new ABNF rule for IPv6address that matches
+ the text representations defined by Section 2.2 of [RFC3513].
+ Likewise, the definition of IPv4address has been improved in order to
+ limit each decimal octet to the range 0-255.
+
+ Section 6, on URI normalization and comparison, has been completely
+ rewritten and extended by using input from Tim Bray and discussion
+ within the W3C Technical Architecture Group.
+
+D.2. Modifications
+
+ The ad-hoc BNF syntax of RFC 2396 has been replaced with the ABNF of
+ [RFC2234]. This change required all rule names that formerly
+ included underscore characters to be renamed with a dash instead. In
+ addition, a number of syntax rules have been eliminated or simplified
+ to make the overall grammar more comprehensible. Specifications that
+ refer to the obsolete grammar rules may be understood by replacing
+ those rules according to the following table:
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 53]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ +----------------+--------------------------------------------------+
+ | obsolete rule | translation |
+ +----------------+--------------------------------------------------+
+ | absoluteURI | absolute-URI |
+ | relativeURI | relative-part [ "?" query ] |
+ | hier_part | ( "//" authority path-abempty / |
+ | | path-absolute ) [ "?" query ] |
+ | | |
+ | opaque_part | path-rootless [ "?" query ] |
+ | net_path | "//" authority path-abempty |
+ | abs_path | path-absolute |
+ | rel_path | path-rootless |
+ | rel_segment | segment-nz-nc |
+ | reg_name | reg-name |
+ | server | authority |
+ | hostport | host [ ":" port ] |
+ | hostname | reg-name |
+ | path_segments | path-abempty |
+ | param | *<pchar excluding ";"> |
+ | | |
+ | uric | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," / "/" |
+ | | |
+ | uric_no_slash | unreserved / pct-encoded / ";" / "?" / ":" |
+ | | / "@" / "&" / "=" / "+" / "$" / "," |
+ | | |
+ | mark | "-" / "_" / "." / "!" / "~" / "*" / "'" |
+ | | / "(" / ")" |
+ | | |
+ | escaped | pct-encoded |
+ | hex | HEXDIG |
+ | alphanum | ALPHA / DIGIT |
+ +----------------+--------------------------------------------------+
+
+ Use of the above obsolete rules for the definition of scheme-specific
+ syntax is deprecated.
+
+ Section 2, on characters, has been rewritten to explain what
+ characters are reserved, when they are reserved, and why they are
+ reserved, even when they are not used as delimiters by the generic
+ syntax. The mark characters that are typically unsafe to decode,
+ including the exclamation mark ("!"), asterisk ("*"), single-quote
+ ("'"), and open and close parentheses ("(" and ")"), have been moved
+ to the reserved set in order to clarify the distinction between
+ reserved and unreserved and, hopefully, to answer the most common
+ question of scheme designers. Likewise, the section on
+ percent-encoded characters has been rewritten, and URI normalizers
+ are now given license to decode any percent-encoded octets
+
+
+
+Berners-Lee, et al. Standards Track [Page 54]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ corresponding to unreserved characters. In general, the terms
+ "escaped" and "unescaped" have been replaced with "percent-encoded"
+ and "decoded", respectively, to reduce confusion with other forms of
+ escape mechanisms.
+
+ The ABNF for URI and URI-reference has been redesigned to make them
+ more friendly to LALR parsers and to reduce complexity. As a result,
+ the layout form of syntax description has been removed, along with
+ the uric, uric_no_slash, opaque_part, net_path, abs_path, rel_path,
+ path_segments, rel_segment, and mark rules. All references to
+ "opaque" URIs have been replaced with a better description of how the
+ path component may be opaque to hierarchy. The relativeURI rule has
+ been replaced with relative-ref to avoid unnecessary confusion over
+ whether they are a subset of URI. The ambiguity regarding the
+ parsing of URI-reference as a URI or a relative-ref with a colon in
+ the first segment has been eliminated through the use of five
+ separate path matching rules.
+
+ The fragment identifier has been moved back into the section on
+ generic syntax components and within the URI and relative-ref rules,
+ though it remains excluded from absolute-URI. The number sign ("#")
+ character has been moved back to the reserved set as a result of
+ reintegrating the fragment syntax.
+
+ The ABNF has been corrected to allow the path component to be empty.
+ This also allows an absolute-URI to consist of nothing after the
+ "scheme:", as is present in practice with the "dav:" namespace
+ [RFC2518] and with the "about:" scheme used internally by many WWW
+ browser implementations. The ambiguity regarding the boundary
+ between authority and path has been eliminated through the use of
+ five separate path matching rules.
+
+ Registry-based naming authorities that use the generic syntax are now
+ defined within the host rule. This change allows current
+ implementations, where whatever name provided is simply fed to the
+ local name resolution mechanism, to be consistent with the
+ specification. It also removes the need to re-specify DNS name
+ formats here. Furthermore, it allows the host component to contain
+ percent-encoded octets, which is necessary to enable
+ internationalized domain names to be provided in URIs, processed in
+ their native character encodings at the application layers above URI
+ processing, and passed to an IDNA library as a registered name in the
+ UTF-8 character encoding. The server, hostport, hostname,
+ domainlabel, toplabel, and alphanum rules have been removed.
+
+ The resolving relative references algorithm of [RFC2396] has been
+ rewritten with pseudocode for this revision to improve clarity and
+ fix the following issues:
+
+
+
+Berners-Lee, et al. Standards Track [Page 55]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ o [RFC2396] section 5.2, step 6a, failed to account for a base URI
+ with no path.
+
+ o Restored the behavior of [RFC1808] where, if the reference
+ contains an empty path and a defined query component, the target
+ URI inherits the base URI's path component.
+
+ o The determination of whether a URI reference is a same-document
+ reference has been decoupled from the URI parser, simplifying the
+ URI processing interface within applications in a way consistent
+ with the internal architecture of deployed URI processing
+ implementations. The determination is now based on comparison to
+ the base URI after transforming a reference to absolute form,
+ rather than on the format of the reference itself. This change
+ may result in more references being considered "same-document"
+ under this specification than there would be under the rules given
+ in RFC 2396, especially when normalization is used to reduce
+ aliases. However, it does not change the status of existing
+ same-document references.
+
+ o Separated the path merge routine into two routines: merge, for
+ describing combination of the base URI path with a relative-path
+ reference, and remove_dot_segments, for describing how to remove
+ the special "." and ".." segments from a composed path. The
+ remove_dot_segments algorithm is now applied to all URI reference
+ paths in order to match common implementations and to improve the
+ normalization of URIs in practice. This change only impacts the
+ parsing of abnormal references and same-scheme references wherein
+ the base URI has a non-hierarchical path.
+
+Index
+
+ A
+ ABNF 11
+ absolute 27
+ absolute-path 26
+ absolute-URI 27
+ access 9
+ authority 17, 18
+
+ B
+ base URI 28
+
+ C
+ character encoding 4
+ character 4
+ characters 8, 11
+ coded character set 4
+
+
+
+Berners-Lee, et al. Standards Track [Page 56]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ D
+ dec-octet 20
+ dereference 9
+ dot-segments 23
+
+ F
+ fragment 16, 24
+
+ G
+ gen-delims 13
+ generic syntax 6
+
+ H
+ h16 20
+ hier-part 16
+ hierarchical 10
+ host 18
+
+ I
+ identifier 5
+ IP-literal 19
+ IPv4 20
+ IPv4address 19, 20
+ IPv6 19
+ IPv6address 19, 20
+ IPvFuture 19
+
+ L
+ locator 7
+ ls32 20
+
+ M
+ merge 32
+
+ N
+ name 7
+ network-path 26
+
+ P
+ path 16, 22, 26
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ path-abempty 16, 22, 26
+ path-absolute 16, 22, 26
+ path-empty 16, 22, 26
+
+
+
+Berners-Lee, et al. Standards Track [Page 57]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ path-rootless 16, 22
+ pchar 23
+ pct-encoded 12
+ percent-encoding 12
+ port 22
+
+ Q
+ query 16, 23
+
+ R
+ reg-name 21
+ registered name 20
+ relative 10, 28
+ relative-path 26
+ relative-ref 26
+ remove_dot_segments 33
+ representation 9
+ reserved 12
+ resolution 9, 28
+ resource 5
+ retrieval 9
+
+ S
+ same-document 27
+ sameness 9
+ scheme 16, 17
+ segment 22, 23
+ segment-nz 23
+ segment-nz-nc 23
+ sub-delims 13
+ suffix 27
+
+ T
+ transcription 8
+
+ U
+ uniform 4
+ unreserved 13
+ URI grammar
+ absolute-URI 27
+ ALPHA 11
+ authority 18
+ CR 11
+ dec-octet 20
+ DIGIT 11
+ DQUOTE 11
+ fragment 24
+ gen-delims 13
+
+
+
+Berners-Lee, et al. Standards Track [Page 58]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+ h16 20
+ HEXDIG 11
+ hier-part 16
+ host 19
+ IP-literal 19
+ IPv4address 20
+ IPv6address 20
+ IPvFuture 19
+ LF 11
+ ls32 20
+ OCTET 11
+ path 22
+ path-abempty 22
+ path-absolute 22
+ path-empty 22
+ path-noscheme 22
+ path-rootless 22
+ pchar 23
+ pct-encoded 12
+ port 22
+ query 24
+ reg-name 21
+ relative-ref 26
+ reserved 13
+ scheme 17
+ segment 23
+ segment-nz 23
+ segment-nz-nc 23
+ SP 11
+ sub-delims 13
+ unreserved 13
+ URI 16
+ URI-reference 25
+ userinfo 18
+ URI 16
+ URI-reference 25
+ URL 7
+ URN 7
+ userinfo 18
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 59]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Authors' Addresses
+
+ Tim Berners-Lee
+ World Wide Web Consortium
+ Massachusetts Institute of Technology
+ 77 Massachusetts Avenue
+ Cambridge, MA 02139
+ USA
+
+ Phone: +1-617-253-5702
+ Fax: +1-617-258-5999
+ EMail: timbl@w3.org
+ URI: http://www.w3.org/People/Berners-Lee/
+
+
+ Roy T. Fielding
+ Day Software
+ 5251 California Ave., Suite 110
+ Irvine, CA 92617
+ USA
+
+ Phone: +1-949-679-2960
+ Fax: +1-949-679-2972
+ EMail: fielding@gbiv.com
+ URI: http://roy.gbiv.com/
+
+
+ Larry Masinter
+ Adobe Systems Incorporated
+ 345 Park Ave
+ San Jose, CA 95110
+ USA
+
+ Phone: +1-408-536-3024
+ EMail: LMM@acm.org
+ URI: http://larry.masinter.net/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 60]
+
+RFC 3986 URI Generic Syntax January 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+Berners-Lee, et al. Standards Track [Page 61]
+
diff --git a/trunk/txt/rfc3987.txt b/trunk/txt/rfc3987.txt
new file mode 100644
index 00000000..f0b1513b
--- /dev/null
+++ b/trunk/txt/rfc3987.txt
@@ -0,0 +1,2579 @@
+
+
+
+
+
+
+Network Working Group M. Duerst
+Request for Comments: 3987 W3C
+Category: Standards Track M. Suignard
+ Microsoft Corporation
+ January 2005
+
+
+ Internationalized Resource Identifiers (IRIs)
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document defines a new protocol element, the Internationalized
+ Resource Identifier (IRI), as a complement to the Uniform Resource
+ Identifier (URI). An IRI is a sequence of characters from the
+ Universal Character Set (Unicode/ISO 10646). A mapping from IRIs to
+ URIs is defined, which means that IRIs can be used instead of URIs,
+ where appropriate, to identify resources.
+
+ The approach of defining a new protocol element was chosen instead of
+ extending or changing the definition of URIs. This was done in order
+ to allow a clear distinction and to avoid incompatibilities with
+ existing software. Guidelines are provided for the use and
+ deployment of IRIs in various protocols, formats, and software
+ components that currently deal with URIs.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Overview and Motivation . . . . . . . . . . . . . . . . 3
+ 1.2. Applicability . . . . . . . . . . . . . . . . . . . . . 3
+ 1.3. Definitions . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.4. Notation . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 2. IRI Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 2.1. Summary of IRI Syntax . . . . . . . . . . . . . . . . . 6
+ 2.2. ABNF for IRI References and IRIs . . . . . . . . . . . . 7
+
+
+
+
+Duerst & Suignard Standards Track [Page 1]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ 3. Relationship between IRIs and URIs . . . . . . . . . . . . . . 10
+ 3.1. Mapping of IRIs to URIs . . . . . . . . . . . . . . . . 10
+ 3.2. Converting URIs to IRIs . . . . . . . . . . . . . . . . 14
+ 3.2.1. Examples . . . . . . . . . . . . . . . . . . . . 15
+ 4. Bidirectional IRIs for Right-to-Left Languages. . . . . . . . 16
+ 4.1. Logical Storage and Visual Presentation . . . . . . . . 17
+ 4.2. Bidi IRI Structure . . . . . . . . . . . . . . . . . . . 18
+ 4.3. Input of Bidi IRIs . . . . . . . . . . . . . . . . . . . 19
+ 4.4. Examples . . . . . . . . . . . . . . . . . . . . . . . . 19
+ 5. Normalization and Comparison . . . . . . . . . . . . . . . . . 21
+ 5.1. Equivalence . . . . . . . . . . . . . . . . . . . . . . 22
+ 5.2. Preparation for Comparison . . . . . . . . . . . . . . . 22
+ 5.3. Comparison Ladder . . . . . . . . . . . . . . . . . . . 23
+ 5.3.1. Simple String Comparison . . . . . . . . . . . . 23
+ 5.3.2. Syntax-Based Normalization . . . . . . . . . . . 24
+ 5.3.3. Scheme-Based Normalization . . . . . . . . . . . 27
+ 5.3.4. Protocol-Based Normalization . . . . . . . . . . 28
+ 6. Use of IRIs . . . . . . . . . . . . . . . . . . . . . . . . . 29
+ 6.1. Limitations on UCS Characters Allowed in IRIs . . . . . 29
+ 6.2. Software Interfaces and Protocols . . . . . . . . . . . 29
+ 6.3. Format of URIs and IRIs in Documents and Protocols . . . 30
+ 6.4. Use of UTF-8 for Encoding Original Characters .. . . . . 30
+ 6.5. Relative IRI References . . . . . . . . . . . . . . . . 32
+ 7. URI/IRI Processing Guidelines (informative) . . . . . . . . . 32
+ 7.1. URI/IRI Software Interfaces . . . . . . . . . . . . . . 32
+ 7.2. URI/IRI Entry . . . . . . . . . . . . . . . . . . . . . 33
+ 7.3. URI/IRI Transfer between Applications . . . . . . . . . 33
+ 7.4. URI/IRI Generation . . . . . . . . . . . . . . . . . . . 34
+ 7.5. URI/IRI Selection . . . . . . . . . . . . . . . . . . . 34
+ 7.6. Display of URIs/IRIs . . . . . . . . . . . . . . . . . . 35
+ 7.7. Interpretation of URIs and IRIs . . . . . . . . . . . . 36
+ 7.8. Upgrading Strategy . . . . . . . . . . . . . . . . . . . 36
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 37
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 39
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 40
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 40
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 41
+ A. Design Alternatives . . . . . . . . . . . . . . . . . . . . . 44
+ A.1. New Scheme(s) . . . . . . . . . . . . . . . . . . . . . 44
+ A.2. Character Encodings Other Than UTF-8 . . . . . . . . . . 44
+ A.3. New Encoding Convention . . . . . . . . . . . . . . . . 44
+ A.4. Indicating Character Encodings in the URI/IRI . . . . . 45
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 45
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 46
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 2]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+1. Introduction
+
+1.1. Overview and Motivation
+
+ A Uniform Resource Identifier (URI) is defined in [RFC3986] as a
+ sequence of characters chosen from a limited subset of the repertoire
+ of US-ASCII [ASCII] characters.
+
+ The characters in URIs are frequently used for representing words of
+ natural languages. This usage has many advantages: Such URIs are
+ easier to memorize, easier to interpret, easier to transcribe, easier
+ to create, and easier to guess. For most languages other than
+ English, however, the natural script uses characters other than A -
+ Z. For many people, handling Latin characters is as difficult as
+ handling the characters of other scripts is for those who use only
+ the Latin alphabet. Many languages with non-Latin scripts are
+ transcribed with Latin letters. These transcriptions are now often
+ used in URIs, but they introduce additional ambiguities.
+
+ The infrastructure for the appropriate handling of characters from
+ local scripts is now widely deployed in local versions of operating
+ system and application software. Software that can handle a wide
+ variety of scripts and languages at the same time is increasingly
+ common. Also, increasing numbers of protocols and formats can carry
+ a wide range of characters.
+
+ This document defines a new protocol element called Internationalized
+ Resource Identifier (IRI) by extending the syntax of URIs to a much
+ wider repertoire of characters. It also defines "internationalized"
+ versions corresponding to other constructs from [RFC3986], such as
+ URI references. The syntax of IRIs is defined in section 2, and the
+ relationship between IRIs and URIs in section 3.
+
+ Using characters outside of A - Z in IRIs brings some difficulties.
+ Section 4 discusses the special case of bidirectional IRIs, section 5
+ various forms of equivalence between IRIs, and section 6 the use of
+ IRIs in different situations. Section 7 gives additional informative
+ guidelines, and section 8 security considerations.
+
+1.2. Applicability
+
+ IRIs are designed to be compatible with recommendations for new URI
+ schemes [RFC2718]. The compatibility is provided by specifying a
+ well-defined and deterministic mapping from the IRI character
+ sequence to the functionally equivalent URI character sequence.
+ Practical use of IRIs (or IRI references) in place of URIs (or URI
+ references) depends on the following conditions being met:
+
+
+
+
+Duerst & Suignard Standards Track [Page 3]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ a. A protocol or format element should be explicitly designated to
+ be able to carry IRIs. The intent is not to introduce IRIs into
+ contexts that are not defined to accept them. For example, XML
+ schema [XMLSchema] has an explicit type "anyURI" that includes
+ IRIs and IRI references. Therefore, IRIs and IRI references can
+ be in attributes and elements of type "anyURI". On the other
+ hand, in the HTTP protocol [RFC2616], the Request URI is defined
+ as a URI, which means that direct use of IRIs is not allowed in
+ HTTP requests.
+
+ b. The protocol or format carrying the IRIs should have a mechanism
+ to represent the wide range of characters used in IRIs, either
+ natively or by some protocol- or format-specific escaping
+ mechanism (for example, numeric character references in [XML1]).
+
+ c. The URI corresponding to the IRI in question has to encode
+ original characters into octets using UTF-8. For new URI
+ schemes, this is recommended in [RFC2718]. It can apply to a
+ whole scheme (e.g., IMAP URLs [RFC2192] and POP URLs [RFC2384],
+ or the URN syntax [RFC2141]). It can apply to a specific part of
+ a URI, such as the fragment identifier (e.g., [XPointer]). It
+ can apply to a specific URI or part(s) thereof. For details,
+ please see section 6.4.
+
+1.3. Definitions
+
+ The following definitions are used in this document; they follow the
+ terms in [RFC2130], [RFC2277], and [ISO10646].
+
+ character: A member of a set of elements used for the organization,
+ control, or representation of data. For example, "LATIN CAPITAL
+ LETTER A" names a character.
+
+ octet: An ordered sequence of eight bits considered as a unit.
+
+ character repertoire: A set of characters (in the mathematical
+ sense).
+
+ sequence of characters: A sequence of characters (one after another).
+
+ sequence of octets: A sequence of octets (one after another).
+
+ character encoding: A method of representing a sequence of characters
+ as a sequence of octets (maybe with variants). Also, a method of
+ (unambiguously) converting a sequence of octets into a sequence of
+ characters.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 4]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ charset: The name of a parameter or attribute used to identify a
+ character encoding.
+
+ UCS: Universal Character Set. The coded character set defined by
+ ISO/IEC 10646 [ISO10646] and the Unicode Standard [UNIV4].
+
+ IRI reference: Denotes the common usage of an Internationalized
+ Resource Identifier. An IRI reference may be absolute or
+ relative. However, the "IRI" that results from such a reference
+ only includes absolute IRIs; any relative IRI references are
+ resolved to their absolute form. Note that in [RFC2396] URIs did
+ not include fragment identifiers, but in [RFC3986] fragment
+ identifiers are part of URIs.
+
+ running text: Human text (paragraphs, sentences, phrases) with syntax
+ according to orthographic conventions of a natural language, as
+ opposed to syntax defined for ease of processing by machines
+ (e.g., markup, programming languages).
+
+ protocol element: Any portion of a message that affects processing of
+ that message by the protocol in question.
+
+ presentation element: A presentation form corresponding to a protocol
+ element; for example, using a wider range of characters.
+
+ create (a URI or IRI): With respect to URIs and IRIs, the term is
+ used for the initial creation. This may be the initial creation
+ of a resource with a certain identifier, or the initial exposition
+ of a resource under a particular identifier.
+
+ generate (a URI or IRI): With respect to URIs and IRIs, the term is
+ used when the IRI is generated by derivation from other
+ information.
+
+1.4. Notation
+
+ RFCs and Internet Drafts currently do not allow any characters
+ outside the US-ASCII repertoire. Therefore, this document uses
+ various special notations to denote such characters in examples.
+
+ In text, characters outside US-ASCII are sometimes referenced by
+ using a prefix of 'U+', followed by four to six hexadecimal digits.
+
+ To represent characters outside US-ASCII in examples, this document
+ uses two notations: 'XML Notation' and 'Bidi Notation'.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 5]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ XML Notation uses a leading '&#x', a trailing ';', and the
+ hexadecimal number of the character in the UCS in between. For
+ example, &#x44F; stands for CYRILLIC CAPITAL LETTER YA. In this
+ notation, an actual '&' is denoted by '&amp;'.
+
+ Bidi Notation is used for bidirectional examples: Lowercase letters
+ stand for Latin letters or other letters that are written left to
+ right, whereas uppercase letters represent Arabic or Hebrew letters
+ that are written right to left.
+
+ To denote actual octets in examples (as opposed to percent-encoded
+ octets), the two hex digits denoting the octet are enclosed in "<"
+ and ">". For example, the octet often denoted as 0xc9 is denoted
+ here as <c9>.
+
+ In this document, the key words "MUST", "MUST NOT", "REQUIRED",
+ "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" are to be interpreted as described in [RFC2119].
+
+2. IRI Syntax
+
+ This section defines the syntax of Internationalized Resource
+ Identifiers (IRIs).
+
+ As with URIs, an IRI is defined as a sequence of characters, not as a
+ sequence of octets. This definition accommodates the fact that IRIs
+ may be written on paper or read over the radio as well as stored or
+ transmitted digitally. The same IRI may be represented as different
+ sequences of octets in different protocols or documents if these
+ protocols or documents use different character encodings (and/or
+ transfer encodings). Using the same character encoding as the
+ containing protocol or document ensures that the characters in the
+ IRI can be handled (e.g., searched, converted, displayed) in the same
+ way as the rest of the protocol or document.
+
+2.1. Summary of IRI Syntax
+
+ IRIs are defined similarly to URIs in [RFC3986], but the class of
+ unreserved characters is extended by adding the characters of the UCS
+ (Universal Character Set, [ISO10646]) beyond U+007F, subject to the
+ limitations given in the syntax rules below and in section 6.1.
+
+ Otherwise, the syntax and use of components and reserved characters
+ is the same as that in [RFC3986]. All the operations defined in
+ [RFC3986], such as the resolution of relative references, can be
+ applied to IRIs by IRI-processing software in exactly the same way as
+ they are for URIs by URI-processing software.
+
+
+
+
+Duerst & Suignard Standards Track [Page 6]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ Characters outside the US-ASCII repertoire are not reserved and
+ therefore MUST NOT be used for syntactical purposes, such as to
+ delimit components in newly defined schemes. For example, U+00A2,
+ CENT SIGN, is not allowed as a delimiter in IRIs, because it is in
+ the 'iunreserved' category. This is similar to the fact that it is
+ not possible to use '-' as a delimiter in URIs, because it is in the
+ 'unreserved' category.
+
+2.2. ABNF for IRI References and IRIs
+
+ Although it might be possible to define IRI references and IRIs
+ merely by their transformation to URI references and URIs, they can
+ also be accepted and processed directly. Therefore, an ABNF
+ definition for IRI references (which are the most general concept and
+ the start of the grammar) and IRIs is given here. The syntax of this
+ ABNF is described in [RFC2234]. Character numbers are taken from the
+ UCS, without implying any actual binary encoding. Terminals in the
+ ABNF are characters, not bytes.
+
+ The following grammar closely follows the URI grammar in [RFC3986],
+ except that the range of unreserved characters is expanded to include
+ UCS characters, with the restriction that private UCS characters can
+ occur only in query parts. The grammar is split into two parts:
+ Rules that differ from [RFC3986] because of the above-mentioned
+ expansion, and rules that are the same as those in [RFC3986]. For
+ rules that are different than those in [RFC3986], the names of the
+ non-terminals have been changed as follows. If the non-terminal
+ contains 'URI', this has been changed to 'IRI'. Otherwise, an 'i'
+ has been prefixed.
+
+ The following rules are different from those in [RFC3986]:
+
+ IRI = scheme ":" ihier-part [ "?" iquery ]
+ [ "#" ifragment ]
+
+ ihier-part = "//" iauthority ipath-abempty
+ / ipath-absolute
+ / ipath-rootless
+ / ipath-empty
+
+ IRI-reference = IRI / irelative-ref
+
+ absolute-IRI = scheme ":" ihier-part [ "?" iquery ]
+
+ irelative-ref = irelative-part [ "?" iquery ] [ "#" ifragment ]
+
+ irelative-part = "//" iauthority ipath-abempty
+ / ipath-absolute
+
+
+
+Duerst & Suignard Standards Track [Page 7]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ / ipath-noscheme
+ / ipath-empty
+
+ iauthority = [ iuserinfo "@" ] ihost [ ":" port ]
+ iuserinfo = *( iunreserved / pct-encoded / sub-delims / ":" )
+ ihost = IP-literal / IPv4address / ireg-name
+
+ ireg-name = *( iunreserved / pct-encoded / sub-delims )
+
+ ipath = ipath-abempty ; begins with "/" or is empty
+ / ipath-absolute ; begins with "/" but not "//"
+ / ipath-noscheme ; begins with a non-colon segment
+ / ipath-rootless ; begins with a segment
+ / ipath-empty ; zero characters
+
+ ipath-abempty = *( "/" isegment )
+ ipath-absolute = "/" [ isegment-nz *( "/" isegment ) ]
+ ipath-noscheme = isegment-nz-nc *( "/" isegment )
+ ipath-rootless = isegment-nz *( "/" isegment )
+ ipath-empty = 0<ipchar>
+
+ isegment = *ipchar
+ isegment-nz = 1*ipchar
+ isegment-nz-nc = 1*( iunreserved / pct-encoded / sub-delims
+ / "@" )
+ ; non-zero-length segment without any colon ":"
+
+ ipchar = iunreserved / pct-encoded / sub-delims / ":"
+ / "@"
+
+ iquery = *( ipchar / iprivate / "/" / "?" )
+
+ ifragment = *( ipchar / "/" / "?" )
+
+ iunreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" / ucschar
+
+ ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
+ / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
+ / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
+ / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
+ / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
+ / %xD0000-DFFFD / %xE1000-EFFFD
+
+ iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD
+
+ Some productions are ambiguous. The "first-match-wins" (a.k.a.
+ "greedy") algorithm applies. For details, see [RFC3986].
+
+
+
+
+Duerst & Suignard Standards Track [Page 8]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ The following rules are the same as those in [RFC3986]:
+
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+
+ port = *DIGIT
+
+ IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+
+ IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+
+ IPv6address = 6( h16 ":" ) ls32
+ / "::" 5( h16 ":" ) ls32
+ / [ h16 ] "::" 4( h16 ":" ) ls32
+ / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ / [ *4( h16 ":" ) h16 ] "::" ls32
+ / [ *5( h16 ":" ) h16 ] "::" h16
+ / [ *6( h16 ":" ) h16 ] "::"
+
+ h16 = 1*4HEXDIG
+ ls32 = ( h16 ":" h16 ) / IPv4address
+
+ IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+
+ dec-octet = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+
+ pct-encoded = "%" HEXDIG HEXDIG
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+ This syntax does not support IPv6 scoped addressing zone identifiers.
+
+
+
+
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 9]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+3. Relationship between IRIs and URIs
+
+ IRIs are meant to replace URIs in identifying resources for
+ protocols, formats, and software components that use a UCS-based
+ character repertoire. These protocols and components may never need
+ to use URIs directly, especially when the resource identifier is used
+ simply for identification purposes. However, when the resource
+ identifier is used for resource retrieval, it is in many cases
+ necessary to determine the associated URI, because currently most
+ retrieval mechanisms are only defined for URIs. In this case, IRIs
+ can serve as presentation elements for URI protocol elements. An
+ example would be an address bar in a Web user agent. (Additional
+ rationale is given in section 3.1.)
+
+3.1. Mapping of IRIs to URIs
+
+ This section defines how to map an IRI to a URI. Everything in this
+ section also applies to IRI references and URI references, as well as
+ to components thereof (for example, fragment identifiers).
+
+ This mapping has two purposes:
+
+ Syntaxical. Many URI schemes and components define additional
+ syntactical restrictions not captured in section 2.2.
+ Scheme-specific restrictions are applied to IRIs by converting
+ IRIs to URIs and checking the URIs against the scheme-specific
+ restrictions.
+
+ Interpretational. URIs identify resources in various ways. IRIs also
+ identify resources. When the IRI is used solely for
+ identification purposes, it is not necessary to map the IRI to a
+ URI (see section 5). However, when an IRI is used for resource
+ retrieval, the resource that the IRI locates is the same as the
+ one located by the URI obtained after converting the IRI according
+ to the procedure defined here. This means that there is no need
+ to define resolution separately on the IRI level.
+
+ Applications MUST map IRIs to URIs by using the following two steps.
+
+ Step 1. Generate a UCS character sequence from the original IRI
+ format. This step has the following three variants,
+ depending on the form of the input:
+
+ a. If the IRI is written on paper, read aloud, or otherwise
+ represented as a sequence of characters independent of
+ any character encoding, represent the IRI as a sequence
+ of characters from the UCS normalized according to
+ Normalization Form C (NFC, [UTR15]).
+
+
+
+Duerst & Suignard Standards Track [Page 10]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ b. If the IRI is in some digital representation (e.g., an
+ octet stream) in some known non-Unicode character
+ encoding, convert the IRI to a sequence of characters
+ from the UCS normalized according to NFC.
+
+ c. If the IRI is in a Unicode-based character encoding (for
+ example, UTF-8 or UTF-16), do not normalize (see section
+ 5.3.2.2 for details). Apply step 2 directly to the
+ encoded Unicode character sequence.
+
+ Step 2. For each character in 'ucschar' or 'iprivate', apply steps
+ 2.1 through 2.3 below.
+
+ 2.1. Convert the character to a sequence of one or more octets
+ using UTF-8 [RFC3629].
+
+ 2.2. Convert each octet to %HH, where HH is the hexadecimal
+ notation of the octet value. Note that this is identical
+ to the percent-encoding mechanism in section 2.1 of
+ [RFC3986]. To reduce variability, the hexadecimal notation
+ SHOULD use uppercase letters.
+
+ 2.3. Replace the original character with the resulting character
+ sequence (i.e., a sequence of %HH triplets).
+
+ The above mapping from IRIs to URIs produces URIs fully conforming to
+ [RFC3986]. The mapping is also an identity transformation for URIs
+ and is idempotent; applying the mapping a second time will not
+ change anything. Every URI is by definition an IRI.
+
+ Systems accepting IRIs MAY convert the ireg-name component of an IRI
+ as follows (before step 2 above) for schemes known to use domain
+ names in ireg-name, if the scheme definition does not allow
+ percent-encoding for ireg-name:
+
+ Replace the ireg-name part of the IRI by the part converted using the
+ ToASCII operation specified in section 4.1 of [RFC3490] on each
+ dot-separated label, and by using U+002E (FULL STOP) as a label
+ separator, with the flag UseSTD3ASCIIRules set to TRUE, and with the
+ flag AllowUnassigned set to FALSE for creating IRIs and set to TRUE
+ otherwise.
+
+
+
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 11]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ The ToASCII operation may fail, but this would mean that the IRI
+ cannot be resolved. This conversion SHOULD be used when the goal is
+ to maximize interoperability with legacy URI resolvers. For example,
+ the IRI
+
+ "http://r&#xE9;sum&#xE9;.example.org"
+
+ may be converted to
+
+ "http://xn--rsum-bpad.example.org"
+
+ instead of
+
+ "http://r%C3%A9sum%C3%A9.example.org".
+
+ An IRI with a scheme that is known to use domain names in ireg-name,
+ but where the scheme definition does not allow percent-encoding for
+ ireg-name, meets scheme-specific restrictions if either the
+ straightforward conversion or the conversion using the ToASCII
+ operation on ireg-name result in an URI that meets the scheme-
+ specific restrictions.
+
+ Such an IRI resolves to the URI obtained after converting the IRI and
+ uses the ToASCII operation on ireg-name. Implementations do not have
+ to do this conversion as long as they produce the same result.
+
+ Note: The difference between variants b and c in step 1 (using
+ normalization with NFC, versus not using any normalization)
+ accounts for the fact that in many non-Unicode character
+ encodings, some text cannot be represented directly. For example,
+ the word "Vietnam" is natively written "Vi&#x1EC7;t Nam"
+ (containing a LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW)
+ in NFC, but a direct transcoding from the windows-1258 character
+ encoding leads to "Vi&#xEA;&#x323;t Nam" (containing a LATIN SMALL
+ LETTER E WITH CIRCUMFLEX followed by a COMBINING DOT BELOW).
+ Direct transcoding of other 8-bit encodings of Vietnamese may lead
+ to other representations.
+
+ Note: The uniform treatment of the whole IRI in step 2 is important
+ to make processing independent of URI scheme. See [Gettys] for an
+ in-depth discussion.
+
+ Note: In practice, whether the general mapping (steps 1 and 2) or the
+ ToASCII operation of [RFC3490] is used for ireg-name will not be
+ noticed if mapping from IRI to URI and resolution is tightly
+ integrated (e.g., carried out in the same user agent). But
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 12]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ conversion using [RFC3490] may be able to better deal with
+ backwards compatibility issues in case mapping and resolution are
+ separated, as in the case of using an HTTP proxy.
+
+ Note: Internationalized Domain Names may be contained in parts of an
+ IRI other than the ireg-name part. It is the responsibility of
+ scheme-specific implementations (if the Internationalized Domain
+ Name is part of the scheme syntax) or of server-side
+ implementations (if the Internationalized Domain Name is part of
+ 'iquery') to apply the necessary conversions at the appropriate
+ point. Example: Trying to validate the Web page at
+ http://r&#xE9;sum&#xE9;.example.org would lead to an IRI of
+ http://validator.w3.org/check?uri=http%3A%2F%2Fr&#xE9;sum&#xE9;.
+ example.org, which would convert to a URI of
+ http://validator.w3.org/check?uri=http%3A%2F%2Fr%C3%A9sum%C3%A9.
+ example.org. The server side implementation would be responsible
+ for making the necessary conversions to be able to retrieve the
+ Web page.
+
+ Systems accepting IRIs MAY also deal with the printable characters in
+ US-ASCII that are not allowed in URIs, namely "<", ">", '"', space,
+ "{", "}", "|", "\", "^", and "`", in step 2 above. If these
+ characters are found but are not converted, then the conversion
+ SHOULD fail. Please note that the number sign ("#"), the percent
+ sign ("%"), and the square bracket characters ("[", "]") are not part
+ of the above list and MUST NOT be converted. Protocols and formats
+ that have used earlier definitions of IRIs including these characters
+ MAY require percent-encoding of these characters as a preprocessing
+ step to extract the actual IRI from a given field. This
+ preprocessing MAY also be used by applications allowing the user to
+ enter an IRI.
+
+ Note: In this process (in step 2.3), characters allowed in URI
+ references and existing percent-encoded sequences are not encoded
+ further. (This mapping is similar to, but different from, the
+ encoding applied when arbitrary content is included in some part
+ of a URI.) For example, an IRI of
+ "http://www.example.org/red%09ros&#xE9;#red" (in XML notation) is
+ converted to
+ "http://www.example.org/red%09ros%C3%A9#red", not to something
+ like
+ "http%3A%2F%2Fwww.example.org%2Fred%2509ros%C3%A9%23red".
+
+ Note: Some older software transcoding to UTF-8 may produce illegal
+ output for some input, in particular for characters outside the
+ BMP (Basic Multilingual Plane). As an example, for the IRI with
+ non-BMP characters (in XML Notation):
+ "http://example.com/&#x10300;&#x10301;&#x10302";
+
+
+
+Duerst & Suignard Standards Track [Page 13]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ which contains the first three letters of the Old Italic alphabet,
+ the correct conversion to a URI is
+ "http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82"
+
+3.2. Converting URIs to IRIs
+
+ In some situations, converting a URI into an equivalent IRI may be
+ desirable. This section gives a procedure for this conversion. The
+ conversion described in this section will always result in an IRI
+ that maps back to the URI used as an input for the conversion (except
+ for potential case differences in percent-encoding and for potential
+ percent-encoded unreserved characters). However, the IRI resulting
+ from this conversion may not be exactly the same as the original IRI
+ (if there ever was one).
+
+ URI-to-IRI conversion removes percent-encodings, but not all
+ percent-encodings can be eliminated. There are several reasons for
+ this:
+
+ 1. Some percent-encodings are necessary to distinguish percent-
+ encoded and unencoded uses of reserved characters.
+
+ 2. Some percent-encodings cannot be interpreted as sequences of
+ UTF-8 octets.
+
+ (Note: The octet patterns of UTF-8 are highly regular.
+ Therefore, there is a very high probability, but no guarantee,
+ that percent-encodings that can be interpreted as sequences of
+ UTF-8 octets actually originated from UTF-8. For a detailed
+ discussion, see [Duerst97].)
+
+ 3. The conversion may result in a character that is not appropriate
+ in an IRI. See sections 2.2, 4.1, and 6.1 for further details.
+
+ Conversion from a URI to an IRI is done by using the following steps
+ (or any other algorithm that produces the same result):
+
+ 1. Represent the URI as a sequence of octets in US-ASCII.
+
+ 2. Convert all percent-encodings ("%" followed by two hexadecimal
+ digits) to the corresponding octets, except those corresponding
+ to "%", characters in "reserved", and characters in US-ASCII not
+ allowed in URIs.
+
+ 3. Re-percent-encode any octet produced in step 2 that is not part
+ of a strictly legal UTF-8 octet sequence.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 14]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ 4. Re-percent-encode all octets produced in step 3 that in UTF-8
+ represent characters that are not appropriate according to
+ sections 2.2, 4.1, and 6.1.
+
+ 5. Interpret the resulting octet sequence as a sequence of characters
+ encoded in UTF-8.
+
+ This procedure will convert as many percent-encoded characters as
+ possible to characters in an IRI. Because there are some choices
+ when step 4 is applied (see section 6.1), results may vary.
+
+ Conversions from URIs to IRIs MUST NOT use any character encoding
+ other than UTF-8 in steps 3 and 4, even if it might be possible to
+ guess from the context that another character encoding than UTF-8 was
+ used in the URI. For example, the URI
+ "http://www.example.org/r%E9sum%E9.html" might with some guessing be
+ interpreted to contain two e-acute characters encoded as iso-8859-1.
+ It must not be converted to an IRI containing these e-acute
+ characters. Otherwise, in the future the IRI will be mapped to
+ "http://www.example.org/r%C3%A9sum%C3%A9.html", which is a different
+ URI from "http://www.example.org/r%E9sum%E9.html".
+
+3.2.1. Examples
+
+ This section shows various examples of converting URIs to IRIs. Each
+ example shows the result after each of the steps 1 through 5 is
+ applied. XML Notation is used for the final result. Octets are
+ denoted by "<" followed by two hexadecimal digits followed by ">".
+
+ The following example contains the sequence "%C3%BC", which is a
+ strictly legal UTF-8 sequence, and which is converted into the actual
+ character U+00FC, LATIN SMALL LETTER U WITH DIAERESIS (also known as
+ u-umlaut).
+
+ 1. http://www.example.org/D%C3%BCrst
+
+ 2. http://www.example.org/D<c3><bc>rst
+
+ 3. http://www.example.org/D<c3><bc>rst
+
+ 4. http://www.example.org/D<c3><bc>rst
+
+ 5. http://www.example.org/D&#xFC;rst
+
+ The following example contains the sequence "%FC", which might
+ represent U+00FC, LATIN SMALL LETTER U WITH DIAERESIS, in the
+ iso-8859-1 character encoding. (It might represent other characters
+ in other character encodings. For example, the octet <fc> in
+
+
+
+Duerst & Suignard Standards Track [Page 15]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ iso-8859-5 represents U+045C, CYRILLIC SMALL LETTER KJE.) Because
+ <fc> is not part of a strictly legal UTF-8 sequence, it is
+ re-percent-encoded in step 3.
+
+ 1. http://www.example.org/D%FCrst
+
+ 2. http://www.example.org/D<fc>rst
+
+ 3. http://www.example.org/D%FCrst
+
+ 4. http://www.example.org/D%FCrst
+
+ 5. http://www.example.org/D%FCrst
+
+ The following example contains "%e2%80%ae", which is the percent-
+ encoded UTF-8 character encoding of U+202E, RIGHT-TO-LEFT OVERRIDE.
+ Section 4.1 forbids the direct use of this character in an IRI.
+ Therefore, the corresponding octets are re-percent-encoded in step 4.
+ This example shows that the case (upper- or lowercase) of letters
+ used in percent-encodings may not be preserved. The example also
+ contains a punycode-encoded domain name label (xn--99zt52a), which is
+ not converted.
+
+ 1. http://xn--99zt52a.example.org/%e2%80%ae
+
+ 2. http://xn--99zt52a.example.org/<e2><80><ae>
+
+ 3. http://xn--99zt52a.example.org/<e2><80><ae>
+
+ 4. http://xn--99zt52a.example.org/%E2%80%AE
+
+ 5. http://xn--99zt52a.example.org/%E2%80%AE
+
+ Implementations with scheme-specific knowledge MAY convert
+ punycode-encoded domain name labels to the corresponding characters
+ by using the ToUnicode procedure. Thus, for the example above, the
+ label "xn--99zt52a" may be converted to U+7D0D U+8C46 (Japanese
+ Natto), leading to the overall IRI of
+ "http://&#x7D0D;&#x8C46;.example.org/%E2%80%AE".
+
+4. Bidirectional IRIs for Right-to-Left Languages
+
+ Some UCS characters, such as those used in the Arabic and Hebrew
+ scripts, have an inherent right-to-left (rtl) writing direction.
+ IRIs containing these characters (called bidirectional IRIs or Bidi
+ IRIs) require additional attention because of the non-trivial
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 16]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ relation between logical representation (used for digital
+ representation and for reading/spelling) and visual representation
+ (used for display/printing).
+
+ Because of the complex interaction between the logical
+ representation, the visual representation, and the syntax of a Bidi
+ IRI, a balance is needed between various requirements. The main
+ requirements are
+
+ 1. user-predictable conversion between visual and logical
+ representation;
+
+ 2. the ability to include a wide range of characters in various
+ parts of the IRI; and
+
+ 3. minor or no changes or restrictions for implementations.
+
+4.1. Logical Storage and Visual Presentation
+
+ When stored or transmitted in digital representation, bidirectional
+ IRIs MUST be in full logical order and MUST conform to the IRI syntax
+ rules (which includes the rules relevant to their scheme). This
+ ensures that bidirectional IRIs can be processed in the same way as
+ other IRIs.
+
+ Bidirectional IRIs MUST be rendered by using the Unicode
+ Bidirectional Algorithm [UNIV4], [UNI9]. Bidirectional IRIs MUST be
+ rendered in the same way as they would be if they were in a
+ left-to-right embedding; i.e., as if they were preceded by U+202A,
+ LEFT-TO-RIGHT EMBEDDING (LRE), and followed by U+202C, POP
+ DIRECTIONAL FORMATTING (PDF). Setting the embedding direction can
+ also be done in a higher-level protocol (e.g., the dir='ltr'
+ attribute in HTML).
+
+ There is no requirement to use the above embedding if the display is
+ still the same without the embedding. For example, a bidirectional
+ IRI in a text with left-to-right base directionality (such as used
+ for English or Cyrillic) that is preceded and followed by whitespace
+ and strong left-to-right characters does not need an embedding.
+ Also, a bidirectional relative IRI reference that only contains
+ strong right-to-left characters and weak characters and that starts
+ and ends with a strong right-to-left character and appears in a text
+ with right-to-left base directionality (such as used for Arabic or
+ Hebrew) and is preceded and followed by whitespace and strong
+ characters does not need an embedding.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 17]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ In some other cases, using U+200E, LEFT-TO-RIGHT MARK (LRM), may be
+ sufficient to force the correct display behavior. However, the
+ details of the Unicode Bidirectional algorithm are not always easy to
+ understand. Implementers are strongly advised to err on the side of
+ caution and to use embedding in all cases where they are not
+ completely sure that the display behavior is unaffected without the
+ embedding.
+
+ The Unicode Bidirectional Algorithm ([UNI9], section 4.3) permits
+ higher-level protocols to influence bidirectional rendering. Such
+ changes by higher-level protocols MUST NOT be used if they change the
+ rendering of IRIs.
+
+ The bidirectional formatting characters that may be used before or
+ after the IRI to ensure correct display are not themselves part of
+ the IRI. IRIs MUST NOT contain bidirectional formatting characters
+ (LRM, RLM, LRE, RLE, LRO, RLO, and PDF). They affect the visual
+ rendering of the IRI but do not appear themselves. It would
+ therefore not be possible to input an IRI with such characters
+ correctly.
+
+4.2. Bidi IRI Structure
+
+ The Unicode Bidirectional Algorithm is designed mainly for running
+ text. To make sure that it does not affect the rendering of
+ bidirectional IRIs too much, some restrictions on bidirectional IRIs
+ are necessary. These restrictions are given in terms of delimiters
+ (structural characters, mostly punctuation such as "@", ".", ":", and
+ "/") and components (usually consisting mostly of letters and
+ digits).
+
+ The following syntax rules from section 2.2 correspond to components
+ for the purpose of Bidi behavior: iuserinfo, ireg-name, isegment,
+ isegment-nz, isegment-nz-nc, ireg-name, iquery, and ifragment.
+
+ Specifications that define the syntax of any of the above components
+ MAY divide them further and define smaller parts to be components
+ according to this document. As an example, the restrictions of
+ [RFC3490] on bidirectional domain names correspond to treating each
+ label of a domain name as a component for schemes with ireg-name as a
+ domain name. Even where the components are not defined formally, it
+ may be helpful to think about some syntax in terms of components and
+ to apply the relevant restrictions. For example, for the usual
+ name/value syntax in query parts, it is convenient to treat each name
+ and each value as a component. As another example, the extensions in
+ a resource name can be treated as separate components.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 18]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ For each component, the following restrictions apply:
+
+ 1. A component SHOULD NOT use both right-to-left and left-to-right
+ characters.
+
+ 2. A component using right-to-left characters SHOULD start and end
+ with right-to-left characters.
+
+ The above restrictions are given as shoulds, rather than as musts.
+ For IRIs that are never presented visually, they are not relevant.
+ However, for IRIs in general, they are very important to ensure
+ consistent conversion between visual presentation and logical
+ representation, in both directions.
+
+ Note: In some components, the above restrictions may actually be
+ strictly enforced. For example, [RFC3490] requires that these
+ restrictions apply to the labels of a host name for those schemes
+ where ireg-name is a host name. In some other components (for
+ example, path components) following these restrictions may not be
+ too difficult. For other components, such as parts of the query
+ part, it may be very difficult to enforce the restrictions because
+ the values of query parameters may be arbitrary character
+ sequences.
+
+ If the above restrictions cannot be satisfied otherwise, the affected
+ component can always be mapped to URI notation as described in
+ section 3.1. Please note that the whole component has to be mapped
+ (see also Example 9 below).
+
+4.3. Input of Bidi IRIs
+
+ Bidi input methods MUST generate Bidi IRIs in logical order while
+ rendering them according to section 4.1. During input, rendering
+ SHOULD be updated after every new character is input to avoid end-
+ user confusion.
+
+4.4. Examples
+
+ This section gives examples of bidirectional IRIs, in Bidi Notation.
+ It shows legal IRIs with the relationship between logical and visual
+ representation and explains how certain phenomena in this
+ relationship may look strange to somebody not familiar with
+ bidirectional behavior, but familiar to users of Arabic and Hebrew.
+ It also shows what happens if the restrictions given in section 4.2
+ are not followed. The examples below can be seen at [BidiEx], in
+ Arabic, Hebrew, and Bidi Notation variants.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 19]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ To read the bidi text in the examples, read the visual representation
+ from left to right until you encounter a block of rtl text. Read the
+ rtl block (including slashes and other special characters) from right
+ to left, then continue at the next unread ltr character.
+
+ Example 1: A single component with rtl characters is inverted:
+ Logical representation: "http://ab.CDEFGH.ij/kl/mn/op.html"
+ Visual representation: "http://ab.HGFEDC.ij/kl/mn/op.html"
+ Components can be read one by one, and each component can be read in
+ its natural direction.
+
+ Example 2: More than one consecutive component with rtl characters is
+ inverted as a whole:
+ Logical representation: "http://ab.CDE.FGH/ij/kl/mn/op.html"
+ Visual representation: "http://ab.HGF.EDC/ij/kl/mn/op.html"
+ A sequence of rtl components is read rtl, in the same way as a
+ sequence of rtl words is read rtl in a bidi text.
+
+ Example 3: All components of an IRI (except for the scheme) are rtl.
+ All rtl components are inverted overall:
+ Logical representation: "http://AB.CD.EF/GH/IJ/KL?MN=OP;QR=ST#UV"
+ Visual representation: "http://VU#TS=RQ;PO=NM?LK/JI/HG/FE.DC.BA"
+ The whole IRI (except the scheme) is read rtl. Delimiters between
+ rtl components stay between the respective components; delimiters
+ between ltr and rtl components don't move.
+
+ Example 4: Each of several sequences of rtl components is inverted on
+ its own:
+ Logical representation: "http://AB.CD.ef/gh/IJ/KL.html"
+ Visual representation: "http://DC.BA.ef/gh/LK/JI.html"
+ Each sequence of rtl components is read rtl, in the same way as each
+ sequence of rtl words in an ltr text is read rtl.
+
+ Example 5: Example 2, applied to components of different kinds:
+ Logical representation: "http://ab.cd.EF/GH/ij/kl.html"
+ Visual representation: "http://ab.cd.HG/FE/ij/kl.html"
+ The inversion of the domain name label and the path component may be
+ unexpected, but it is consistent with other bidi behavior. For
+ reassurance that the domain component really is "ab.cd.EF", it may be
+ helpful to read aloud the visual representation following the bidi
+ algorithm. After "http://ab.cd." one reads the RTL block
+ "E-F-slash-G-H", which corresponds to the logical representation.
+
+ Example 6: Same as Example 5, with more rtl components:
+ Logical representation: "http://ab.CD.EF/GH/IJ/kl.html"
+ Visual representation: "http://ab.JI/HG/FE.DC/kl.html"
+ The inversion of the domain name labels and the path components may
+ be easier to identify because the delimiters also move.
+
+
+
+Duerst & Suignard Standards Track [Page 20]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ Example 7: A single rtl component includes digits:
+ Logical representation: "http://ab.CDE123FGH.ij/kl/mn/op.html"
+ Visual representation: "http://ab.HGF123EDC.ij/kl/mn/op.html"
+ Numbers are written ltr in all cases but are treated as an additional
+ embedding inside a run of rtl characters. This is completely
+ consistent with usual bidirectional text.
+
+ Example 8 (not allowed): Numbers are at the start or end of an rtl
+ component:
+ Logical representation: "http://ab.cd.ef/GH1/2IJ/KL.html"
+ Visual representation: "http://ab.cd.ef/LK/JI1/2HG.html"
+ The sequence "1/2" is interpreted by the bidi algorithm as a
+ fraction, fragmenting the components and leading to confusion. There
+ are other characters that are interpreted in a special way close to
+ numbers; in particular, "+", "-", "#", "$", "%", ",", ".", and ":".
+
+ Example 9 (not allowed): The numbers in the previous example are
+ percent-encoded:
+ Logical representation: "http://ab.cd.ef/GH%31/%32IJ/KL.html",
+ Visual representation (Hebrew): "http://ab.cd.ef/%31HG/LK/JI%32.html"
+ Visual representation (Arabic): "http://ab.cd.ef/31%HG/%LK/JI32.html"
+ Depending on whether the uppercase letters represent Arabic or
+ Hebrew, the visual representation is different.
+
+ Example 10 (allowed but not recommended):
+ Logical representation: "http://ab.CDEFGH.123/kl/mn/op.html"
+ Visual representation: "http://ab.123.HGFEDC/kl/mn/op.html"
+ Components consisting of only numbers are allowed (it would be rather
+ difficult to prohibit them), but these may interact with adjacent RTL
+ components in ways that are not easy to predict.
+
+5. Normalization and Comparison
+
+ Note: The structure and much of the material for this section is
+ taken from section 6 of [RFC3986]; the differences are due to the
+ specifics of IRIs.
+
+ One of the most common operations on IRIs is simple comparison:
+ Determining whether two IRIs are equivalent without using the IRIs or
+ the mapped URIs to access their respective resource(s). A comparison
+ is performed whenever a response cache is accessed, a browser checks
+ its history to color a link, or an XML parser processes tags within a
+ namespace. Extensive normalization prior to comparison of IRIs may
+ be used by spiders and indexing engines to prune a search space or
+ reduce duplication of request actions and response storage.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 21]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ IRI comparison is performed for some particular purpose. Protocols
+ or implementations that compare IRIs for different purposes will
+ often be subject to differing design trade-offs in regards to how
+ much effort should be spent in reducing aliased identifiers. This
+ section describes various methods that may be used to compare IRIs,
+ the trade-offs between them, and the types of applications that might
+ use them.
+
+5.1. Equivalence
+
+ Because IRIs exist to identify resources, presumably they should be
+ considered equivalent when they identify the same resource. However,
+ this definition of equivalence is not of much practical use, as there
+ is no way for an implementation to compare two resources unless it
+ has full knowledge or control of them. For this reason, determination
+ of equivalence or difference of IRIs is based on string comparison,
+ perhaps augmented by reference to additional rules provided by URI
+ scheme definitions. We use the terms "different" and "equivalent" to
+ describe the possible outcomes of such comparisons, but there are
+ many application-dependent versions of equivalence.
+
+ Even though it is possible to determine that two IRIs are equivalent,
+ IRI comparison is not sufficient to determine whether two IRIs
+ identify different resources. For example, an owner of two different
+ domain names could decide to serve the same resource from both,
+ resulting in two different IRIs. Therefore, comparison methods are
+ designed to minimize false negatives while strictly avoiding false
+ positives.
+
+ In testing for equivalence, applications should not directly compare
+ relative references; the references should be converted to their
+ respective target IRIs before comparison. When IRIs are compared to
+ select (or avoid) a network action, such as retrieval of a
+ representation, fragment components (if any) should be excluded from
+ the comparison.
+
+ Applications using IRIs as identity tokens with no relationship to a
+ protocol MUST use the Simple String Comparison (see section 5.3.1).
+ All other applications MUST select one of the comparison practices
+ from the Comparison Ladder (see section 5.3 or, after IRI-to-URI
+ conversion, select one of the comparison practices from the URI
+ comparison ladder in [RFC3986], section 6.2)
+
+5.2. Preparation for Comparison
+
+ Any kind of IRI comparison REQUIRES that all escapings or encodings
+ in the protocol or format that carries an IRI are resolved. This is
+ usually done when the protocol or format is parsed. Examples of such
+
+
+
+Duerst & Suignard Standards Track [Page 22]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ escapings or encodings are entities and numeric character references
+ in [HTML4] and [XML1]. As an example,
+ "http://example.org/ros&eacute;" (in HTML),
+ "http://example.org/ros&#233"; (in HTML or XML), and
+ "http://example.org/ros&#xE9"; (in HTML or XML) are all resolved into
+ what is denoted in this document (see section 1.4) as
+ "http://example.org/ros&#xE9"; (the "&#xE9;" here standing for the
+ actual e-acute character, to compensate for the fact that this
+ document cannot contain non-ASCII characters).
+
+ Similar considerations apply to encodings such as Transfer Codings in
+ HTTP (see [RFC2616]) and Content Transfer Encodings in MIME
+ ([RFC2045]), although in these cases, the encoding is based not on
+ characters but on octets, and additional care is required to make
+ sure that characters, and not just arbitrary octets, are compared
+ (see section 5.3.1).
+
+5.3. Comparison Ladder
+
+ In practice, a variety of methods are used, to test IRI equivalence.
+ These methods fall into a range distinguished by the amount of
+ processing required and the degree to which the probability of false
+ negatives is reduced. As noted above, false negatives cannot be
+ eliminated. In practice, their probability can be reduced, but this
+ reduction requires more processing and is not cost-effective for all
+ applications.
+
+ If this range of comparison practices is considered as a ladder, the
+ following discussion will climb the ladder, starting with practices
+ that are cheap but have a relatively higher chance of producing false
+ negatives, and proceeding to those that have higher computational
+ cost and lower risk of false negatives.
+
+5.3.1. Simple String Comparison
+
+ If two IRIs, when considered as character strings, are identical,
+ then it is safe to conclude that they are equivalent. This type of
+ equivalence test has very low computational cost and is in wide use
+ in a variety of applications, particularly in the domain of parsing.
+ It is also used when a definitive answer to the question of IRI
+ equivalence is needed that is independent of the scheme used and that
+ can be calculated quickly and without accessing a network. An
+ example of such a case is XML Namespaces ([XMLNamespace]).
+
+ Testing strings for equivalence requires some basic precautions. This
+ procedure is often referred to as "bit-for-bit" or "byte-for-byte"
+ comparison, which is potentially misleading. Testing strings for
+ equality is normally based on pair comparison of the characters that
+
+
+
+Duerst & Suignard Standards Track [Page 23]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ make up the strings, starting from the first and proceeding until
+ both strings are exhausted and all characters are found to be equal,
+ until a pair of characters compares unequal, or until one of the
+ strings is exhausted before the other.
+
+ This character comparison requires that each pair of characters be
+ put in comparable encoding form. For example, should one IRI be
+ stored in a byte array in UTF-8 encoding form and the second in a
+ UTF-16 encoding form, bit-for-bit comparisons applied naively will
+ produce errors. It is better to speak of equality on a
+ character-for-character rather than on a byte-for-byte or bit-for-bit
+ basis. In practical terms, character-by-character comparisons should
+ be done codepoint by codepoint after conversion to a common character
+ encoding form. When comparing character by character, the comparison
+ function MUST NOT map IRIs to URIs, because such a mapping would
+ create additional spurious equivalences. It follows that an IRI
+ SHOULD NOT be modified when being transported if there is any chance
+ that this IRI might be used as an identifier.
+
+ False negatives are caused by the production and use of IRI aliases.
+ Unnecessary aliases can be reduced, regardless of the comparison
+ method, by consistently providing IRI references in an already
+ normalized form (i.e., a form identical to what would be produced
+ after normalization is applied, as described below). Protocols and
+ data formats often limit some IRI comparisons to simple string
+ comparison, based on the theory that people and implementations will,
+ in their own best interest, be consistent in providing IRI
+ references, or at least be consistent enough to negate any efficiency
+ that might be obtained from further normalization.
+
+5.3.2. Syntax-Based Normalization
+
+ Implementations may use logic based on the definitions provided by
+ this specification to reduce the probability of false negatives. This
+ processing is moderately higher in cost than character-for-character
+ string comparison. For example, an application using this approach
+ could reasonably consider the following two IRIs equivalent:
+
+ example://a/b/c/%7Bfoo%7D/ros&#xE9;
+ eXAMPLE://a/./b/../b/%63/%7bfoo%7d/ros%C3%A9
+
+ Web user agents, such as browsers, typically apply this type of IRI
+ normalization when determining whether a cached response is
+ available. Syntax-based normalization includes such techniques as
+ case normalization, character normalization, percent-encoding
+ normalization, and removal of dot-segments.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 24]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+5.3.2.1. Case Normalization
+
+ For all IRIs, the hexadecimal digits within a percent-encoding
+ triplet (e.g., "%3a" versus "%3A") are case-insensitive and therefore
+ should be normalized to use uppercase letters for the digits A - F.
+
+ When an IRI uses components of the generic syntax, the component
+ syntax equivalence rules always apply; namely, that the scheme and
+ US-ASCII only host are case insensitive and therefore should be
+ normalized to lowercase. For example, the URI
+ "HTTP://www.EXAMPLE.com/" is equivalent to "http://www.example.com/".
+ Case equivalence for non-ASCII characters in IRI components that are
+ IDNs are discussed in section 5.3.3. The other generic syntax
+ components are assumed to be case sensitive unless specifically
+ defined otherwise by the scheme.
+
+ Creating schemes that allow case-insensitive syntax components
+ containing non-ASCII characters should be avoided. Case normalization
+ of non-ASCII characters can be culturally dependent and is always a
+ complex operation. The only exception concerns non-ASCII host names
+ for which the character normalization includes a mapping step derived
+ from case folding.
+
+5.3.2.2. Character Normalization
+
+ The Unicode Standard [UNIV4] defines various equivalences between
+ sequences of characters for various purposes. Unicode Standard Annex
+ #15 [UTR15] defines various Normalization Forms for these
+ equivalences, in particular Normalization Form C (NFC, Canonical
+ Decomposition, followed by Canonical Composition) and Normalization
+ Form KC (NFKC, Compatibility Decomposition, followed by Canonical
+ Composition).
+
+ Equivalence of IRIs MUST rely on the assumption that IRIs are
+ appropriately pre-character-normalized rather than apply character
+ normalization when comparing two IRIs. The exceptions are conversion
+ from a non-digital form, and conversion from a non-UCS-based
+ character encoding to a UCS-based character encoding. In these cases,
+ NFC or a normalizing transcoder using NFC MUST be used for
+ interoperability. To avoid false negatives and problems with
+ transcoding, IRIs SHOULD be created by using NFC. Using NFKC may
+ avoid even more problems; for example, by choosing half-width Latin
+ letters instead of full-width ones, and full-width instead of
+ half-width Katakana.
+
+ As an example, "http://www.example.org/r&#xE9;sum&#xE9;.html" (in XML
+ Notation) is in NFC. On the other hand,
+ "http://www.example.org/re&#x301;sume&#x301;.html" is not in NFC.
+
+
+
+Duerst & Suignard Standards Track [Page 25]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ The former uses precombined e-acute characters, and the latter uses
+ "e" characters followed by combining acute accents. Both usages are
+ defined as canonically equivalent in [UNIV4].
+
+ Note: Because it is unknown how a particular sequence of characters
+ is being treated with respect to character normalization, it would
+ be inappropriate to allow third parties to normalize an IRI
+ arbitrarily. This does not contradict the recommendation that
+ when a resource is created, its IRI should be as character
+ normalized as possible (i.e., NFC or even NFKC). This is similar
+ to the uppercase/lowercase problems. Some parts of a URI are case
+ insensitive (domain name). For others, it is unclear whether they
+ are case sensitive, case insensitive, or something in between
+ (e.g., case sensitive, but with a multiple choice selection if the
+ wrong case is used, instead of a direct negative result). The
+ best recipe is that the creator use a reasonable capitalization
+ and, when transferring the URI, capitalization never be changed.
+
+ Various IRI schemes may allow the usage of Internationalized Domain
+ Names (IDN) [RFC3490] either in the ireg-name part or elsewhere.
+ Character Normalization also applies to IDNs, as discussed in section
+ 5.3.3.
+
+5.3.2.3. Percent-Encoding Normalization
+
+ The percent-encoding mechanism (section 2.1 of [RFC3986]) is a
+ frequent source of variance among otherwise identical IRIs. In
+ addition to the case normalization issue noted above, some IRI
+ producers percent-encode octets that do not require percent-encoding,
+ resulting in IRIs that are equivalent to their non encoded
+ counterparts. These IRIs should be normalized by decoding any
+ percent-encoded octet sequence that corresponds to an unreserved
+ character, as described in section 2.3 of [RFC3986].
+
+ For actual resolution, differences in percent-encoding (except for
+ the percent-encoding of reserved characters) MUST always result in
+ the same resource. For example, "http://example.org/~user",
+ "http://example.org/%7euser", and "http://example.org/%7Euser", must
+ resolve to the same resource.
+
+ If this kind of equivalence is to be tested, the percent-encoding of
+ both IRIs to be compared has to be aligned; for example, by
+ converting both IRIs to URIs (see section 3.1), eliminating escape
+ differences in the resulting URIs, and making sure that the case of
+ the hexadecimal characters in the percent-encoding is always the same
+ (preferably uppercase). If the IRI is to be passed to another
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 26]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ application or used further in some other way, its original form MUST
+ be preserved. The conversion described here should be performed only
+ for local comparison.
+
+5.3.2.4. Path Segment Normalization
+
+ The complete path segments "." and ".." are intended only for use
+ within relative references (section 4.1 of [RFC3986]) and are removed
+ as part of the reference resolution process (section 5.2 of
+ [RFC3986]). However, some implementations may incorrectly assume
+ that reference resolution is not necessary when the reference is
+ already an IRI, and thus fail to remove dot-segments when they occur
+ in non-relative paths. IRI normalizers should remove dot-segments by
+ applying the remove_dot_segments algorithm to the path, as described
+ in section 5.2.4 of [RFC3986].
+
+5.3.3. Scheme-Based Normalization
+
+ The syntax and semantics of IRIs vary from scheme to scheme, as
+ described by the defining specification for each scheme.
+ Implementations may use scheme-specific rules, at further processing
+ cost, to reduce the probability of false negatives. For example,
+ because the "http" scheme makes use of an authority component, has a
+ default port of "80", and defines an empty path to be equivalent to
+ "/", the following four IRIs are equivalent:
+
+ http://example.com
+ http://example.com/
+ http://example.com:/
+ http://example.com:80/
+
+ In general, an IRI that uses the generic syntax for authority with an
+ empty path should be normalized to a path of "/". Likewise, an
+ explicit ":port", for which the port is empty or the default for the
+ scheme, is equivalent to one where the port and its ":" delimiter are
+ elided and thus should be removed by scheme-based normalization. For
+ example, the second IRI above is the normal form for the "http"
+ scheme.
+
+ Another case where normalization varies by scheme is in the handling
+ of an empty authority component or empty host subcomponent. For many
+ scheme specifications, an empty authority or host is considered an
+ error; for others, it is considered equivalent to "localhost" or the
+ end-user's host. When a scheme defines a default for authority and
+ an IRI reference to that default is desired, the reference should be
+ normalized to an empty authority for the sake of uniformity, brevity,
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 27]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ and internationalization. If, however, either the userinfo or port
+ subcomponents are non-empty, then the host should be given explicitly
+ even if it matches the default.
+
+ Normalization should not remove delimiters when their associated
+ component is empty unless it is licensed to do so by the scheme
+ specification. For example, the IRI "http://example.com/?" cannot be
+ assumed to be equivalent to any of the examples above. Likewise, the
+ presence or absence of delimiters within a userinfo subcomponent is
+ usually significant to its interpretation. The fragment component is
+ not subject to any scheme-based normalization; thus, two IRIs that
+ differ only by the suffix "#" are considered different regardless of
+ the scheme.
+
+ Some IRI schemes may allow the usage of Internationalized Domain
+ Names (IDN) [RFC3490] either in their ireg-name part or elsewhere.
+ When in use in IRIs, those names SHOULD be validated by using the
+ ToASCII operation defined in [RFC3490], with the flags
+ "UseSTD3ASCIIRules" and "AllowUnassigned". An IRI containing an
+ invalid IDN cannot successfully be resolved. Validated IDN
+ components of IRIs SHOULD be character normalized by using the
+ Nameprep process [RFC3491]; however, for legibility purposes, they
+ SHOULD NOT be converted into ASCII Compatible Encoding (ACE).
+
+ Scheme-based normalization may also consider IDN components and their
+ conversions to punycode as equivalent. As an example,
+ "http://r&#xE9;sum&#xE9;.example.org" may be considered equivalent to
+ "http://xn--rsum-bpad.example.org".
+
+ Other scheme-specific normalizations are possible.
+
+5.3.4. Protocol-Based Normalization
+
+ Substantial effort to reduce the incidence of false negatives is
+ often cost-effective for web spiders. Consequently, they implement
+ even more aggressive techniques in IRI comparison. For example, if
+ they observe that an IRI such as
+
+ http://example.com/data
+
+ redirects to an IRI differing only in the trailing slash
+
+ http://example.com/data/
+
+ they will likely regard the two as equivalent in the future. This
+ kind of technique is only appropriate when equivalence is clearly
+ indicated by both the result of accessing the resources and the
+
+
+
+
+Duerst & Suignard Standards Track [Page 28]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ common conventions of their scheme's dereference algorithm (in this
+ case, use of redirection by HTTP origin servers to avoid problems
+ with relative references).
+
+6. Use of IRIs
+
+6.1. Limitations on UCS Characters Allowed in IRIs
+
+ This section discusses limitations on characters and character
+ sequences usable for IRIs beyond those given in section 2.2 and
+ section 4.1. The considerations in this section are relevant when
+ IRIs are created and when URIs are converted to IRIs.
+
+ a. The repertoire of characters allowed in each IRI component is
+ limited by the definition of that component. For example, the
+ definition of the scheme component does not allow characters
+ beyond US-ASCII.
+
+ (Note: In accordance with URI practice, generic IRI software
+ cannot and should not check for such limitations.)
+
+ b. The UCS contains many areas of characters for which there are
+ strong visual look-alikes. Because of the likelihood of
+ transcription errors, these also should be avoided. This
+ includes the full-width equivalents of Latin characters,
+ half-width Katakana characters for Japanese, and many others. It
+ also includes many look-alikes of "space", "delims", and
+ "unwise", characters excluded in [RFC3491].
+
+ Additional information is available from [UNIXML]. [UNIXML] is
+ written in the context of running text rather than in that of
+ identifiers. Nevertheless, it discusses many of the categories of
+ characters not appropriate for IRIs.
+
+6.2. Software Interfaces and Protocols
+
+ Although an IRI is defined as a sequence of characters, software
+ interfaces for URIs typically function on sequences of octets or
+ other kinds of code units. Thus, software interfaces and protocols
+ MUST define which character encoding is used.
+
+ Intermediate software interfaces between IRI-capable components and
+ URI-only components MUST map the IRIs per section 3.1, when
+ transferring from IRI-capable to URI-only components. This mapping
+ SHOULD be applied as late as possible. It SHOULD NOT be applied
+ between components that are known to be able to handle IRIs.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 29]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+6.3. Format of URIs and IRIs in Documents and Protocols
+
+ Document formats that transport URIs may have to be upgraded to allow
+ the transport of IRIs. In cases where the document as a whole has a
+ native character encoding, IRIs MUST also be encoded in this
+ character encoding and converted accordingly by a parser or
+ interpreter. IRI characters not expressible in the native character
+ encoding SHOULD be escaped by using the escaping conventions of the
+ document format if such conventions are available. Alternatively,
+ they MAY be percent-encoded according to section 3.1. For example, in
+ HTML or XML, numeric character references SHOULD be used. If a
+ document as a whole has a native character encoding and that
+ character encoding is not UTF-8, then IRIs MUST NOT be placed into
+ the document in the UTF-8 character encoding.
+
+ Note: Some formats already accommodate IRIs, although they use
+ different terminology. HTML 4.0 [HTML4] defines the conversion from
+ IRIs to URIs as error-avoiding behavior. XML 1.0 [XML1], XLink
+ [XLink], XML Schema [XMLSchema], and specifications based upon them
+ allow IRIs. Also, it is expected that all relevant new W3C formats
+ and protocols will be required to handle IRIs [CharMod].
+
+6.4. Use of UTF-8 for Encoding Original Characters
+
+ This section discusses details and gives examples for point c) in
+ section 1.2. To be able to use IRIs, the URI corresponding to the
+ IRI in question has to encode original characters into octets by
+ using UTF-8. This can be specified for all URIs of a URI scheme or
+ can apply to individual URIs for schemes that do not specify how to
+ encode original characters. It can apply to the whole URI, or only
+ to some part. For background information on encoding characters into
+ URIs, see also section 2.5 of [RFC3986].
+
+ For new URI schemes, using UTF-8 is recommended in [RFC2718].
+ Examples where UTF-8 is already used are the URN syntax [RFC2141],
+ IMAP URLs [RFC2192], and POP URLs [RFC2384]. On the other hand,
+ because the HTTP URL scheme does not specify how to encode original
+ characters, only some HTTP URLs can have corresponding but different
+ IRIs.
+
+ For example, for a document with a URI of
+ "http://www.example.org/r%C3%A9sum%C3%A9.html", it is possible to
+ construct a corresponding IRI (in XML notation, see, section 1.4):
+ "http://www.example.org/r&#xE9;sum&#xE9;.html" ("&#xE9"; stands for
+ the e-acute character, and "%C3%A9" is the UTF-8 encoded and
+ percent-encoded representation of that character). On the other
+ hand, for a document with a URI of
+
+
+
+
+Duerst & Suignard Standards Track [Page 30]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ "http://www.example.org/r%E9sum%E9.html", the percent-encoding octets
+ cannot be converted to actual characters in an IRI, as the
+ percent-encoding is not based on UTF-8.
+
+ This means that for most URI schemes, there is no need to upgrade
+ their scheme definition in order for them to work with IRIs. The
+ main case where upgrading makes sense is when a scheme definition, or
+ a particular component of a scheme, is strictly limited to the use of
+ US-ASCII characters with no provision to include non-ASCII
+ characters/octets via percent-encoding, or if a scheme definition
+ currently uses highly scheme-specific provisions for the encoding of
+ non-ASCII characters. An example of this is the mailto: scheme
+ [RFC2368].
+
+ This specification does not upgrade any scheme specifications in any
+ way; this has to be done separately. Also, note that there is no
+ such thing as an "IRI scheme"; all IRIs use URI schemes, and all URI
+ schemes can be used with IRIs, even though in some cases only by
+ using URIs directly as IRIs, without any conversion.
+
+ URI schemes can impose restrictions on the syntax of scheme-specific
+ URIs; i.e., URIs that are admissible under the generic URI syntax
+ [RFC3986] may not be admissible due to narrower syntactic constraints
+ imposed by a URI scheme specification. URI scheme definitions cannot
+ broaden the syntactic restrictions of the generic URI syntax;
+ otherwise, it would be possible to generate URIs that satisfied the
+ scheme-specific syntactic constraints without satisfying the
+ syntactic constraints of the generic URI syntax. However, additional
+ syntactic constraints imposed by URI scheme specifications are
+ applicable to IRI, as the corresponding URI resulting from the
+ mapping defined in section 3.1 MUST be a valid URI under the
+ syntactic restrictions of generic URI syntax and any narrower
+ restrictions imposed by the corresponding URI scheme specification.
+
+ The requirement for the use of UTF-8 applies to all parts of a URI
+ (with the potential exception of the ireg-name part; see section
+ 3.1). However, it is possible that the capability of IRIs to
+ represent a wide range of characters directly is used just in some
+ parts of the IRI (or IRI reference). The other parts of the IRI may
+ only contain US-ASCII characters, or they may not be based on UTF-8.
+ They may be based on another character encoding, or they may directly
+ encode raw binary data (see also [RFC2397]).
+
+ For example, it is possible to have a URI reference of
+ "http://www.example.org/r%E9sum%E9.xml#r%C3%A9sum%C3%A9", where the
+ document name is encoded in iso-8859-1 based on server settings, but
+ where the fragment identifier is encoded in UTF-8 according to
+
+
+
+
+Duerst & Suignard Standards Track [Page 31]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ [XPointer]. The IRI corresponding to the above URI would be (in XML
+ notation)
+ "http://www.example.org/r%E9sum%E9.xml#r&#xE9;sum&#xE9";.
+
+ Similar considerations apply to query parts. The functionality of
+ IRIs (namely, to be able to include non-ASCII characters) can only be
+ used if the query part is encoded in UTF-8.
+
+6.5. Relative IRI References
+
+ Processing of relative IRI references against a base is handled
+ straightforwardly; the algorithms of [RFC3986] can be applied
+ directly, treating the characters additionally allowed in IRI
+ references in the same way that unreserved characters are in URI
+ references.
+
+7. URI/IRI Processing Guidelines (Informative)
+
+ This informative section provides guidelines for supporting IRIs in
+ the same software components and operations that currently process
+ URIs: Software interfaces that handle URIs, software that allows
+ users to enter URIs, software that creates or generates URIs,
+ software that displays URIs, formats and protocols that transport
+ URIs, and software that interprets URIs. These may all require
+ modification before functioning properly with IRIs. The
+ considerations in this section also apply to URI references and IRI
+ references.
+
+7.1. URI/IRI Software Interfaces
+
+ Software interfaces that handle URIs, such as URI-handling APIs and
+ protocols transferring URIs, need interfaces and protocol elements
+ that are designed to carry IRIs.
+
+ In case the current handling in an API or protocol is based on
+ US-ASCII, UTF-8 is recommended as the character encoding for IRIs, as
+ it is compatible with US-ASCII, is in accordance with the
+ recommendations of [RFC2277], and makes converting to URIs easy. In
+ any case, the API or protocol definition must clearly define the
+ character encoding to be used.
+
+ The transfer from URI-only to IRI-capable components requires no
+ mapping, although the conversion described in section 3.2 above may
+ be performed. It is preferable not to perform this inverse
+ conversion when there is a chance that this cannot be done correctly.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 32]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+7.2. URI/IRI Entry
+
+ Some components allow users to enter URIs into the system by typing
+ or dictation, for example. This software must be updated to allow
+ for IRI entry.
+
+ A person viewing a visual representation of an IRI (as a sequence of
+ glyphs, in some order, in some visual display) or hearing an IRI will
+ use an entry method for characters in the user's language to input
+ the IRI. Depending on the script and the input method used, this may
+ be a more or less complicated process.
+
+ The process of IRI entry must ensure, as much as possible, that the
+ restrictions defined in section 2.2 are met. This may be done by
+ choosing appropriate input methods or variants/settings thereof, by
+ appropriately converting the characters being input, by eliminating
+ characters that cannot be converted, and/or by issuing a warning or
+ error message to the user.
+
+ As an example of variant settings, input method editors for East
+ Asian Languages usually allow the input of Latin letters and related
+ characters in full-width or half-width versions. For IRI input, the
+ input method editor should be set so that it produces half-width
+ Latin letters and punctuation and full-width Katakana.
+
+ An input field primarily or solely used for the input of URIs/IRIs
+ may allow the user to view an IRI as it is mapped to a URI. Places
+ where the input of IRIs is frequent may provide the possibility for
+ viewing an IRI as mapped to a URI. This will help users when some of
+ the software they use does not yet accept IRIs.
+
+ An IRI input component interfacing to components that handle URIs,
+ but not IRIs, must map the IRI to a URI before passing it to these
+ components.
+
+ For the input of IRIs with right-to-left characters, please see
+ section 4.3.
+
+7.3. URI/IRI Transfer between Applications
+
+ Many applications, particularly mail user agents, try to detect URIs
+ appearing in plain text. For this, they use some heuristics based on
+ URI syntax. They then allow the user to click on such URIs and
+ retrieve the corresponding resource in an appropriate (usually
+ scheme-dependent) application.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 33]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ Such applications have to be upgraded to use the IRI syntax as a base
+ for heuristics. In particular, a non-ASCII character should not be
+ taken as the indication of the end of an IRI. Such applications also
+ have to make sure that they correctly convert the detected IRI from
+ the character encoding of the document or application where the IRI
+ appears to the character encoding used by the system-wide IRI
+ invocation mechanism, or to a URI (according to section 3.1) if the
+ system-wide invocation mechanism only accepts URIs.
+
+ The clipboard is another frequently used way to transfer URIs and
+ IRIs from one application to another. On most platforms, the
+ clipboard is able to store and transfer text in many languages and
+ scripts. Correctly used, the clipboard transfers characters, not
+ bytes, which will do the right thing with IRIs.
+
+7.4. URI/IRI Generation
+
+ Systems that offer resources through the Internet, where those
+ resources have logical names, sometimes automatically generate URIs
+ for the resources they offer. For example, some HTTP servers can
+ generate a directory listing for a file directory and then respond to
+ the generated URIs with the files.
+
+ Many legacy character encodings are in use in various file systems.
+ Many currently deployed systems do not transform the local character
+ representation of the underlying system before generating URIs.
+
+ For maximum interoperability, systems that generate resource
+ identifiers should make the appropriate transformations. For
+ example, if a file system contains a file named
+ "r&#xE9;sum&#xE9;.html", a server should expose this as
+ "r%C3%A9sum%C3%A9.html" in a URI, which allows use of
+ "r&#xE9;sum&#xE9;.html" in an IRI, even if locally the file name is
+ kept in a character encoding other than UTF-8.
+
+ This recommendation particularly applies to HTTP servers. For FTP
+ servers, similar considerations apply; see [RFC2640].
+
+7.5. URI/IRI Selection
+
+ In some cases, resource owners and publishers have control over the
+ IRIs used to identify their resources. This control is mostly
+ executed by controlling the resource names, such as file names,
+ directly.
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 34]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ In these cases, it is recommended to avoid choosing IRIs that are
+ easily confused. For example, for US-ASCII, the lower-case ell ("l")
+ is easily confused with the digit one ("1"), and the upper-case oh
+ ("O") is easily confused with the digit zero ("0"). Publishers
+ should avoid confusing users with "br0ken" or "1ame" identifiers.
+
+ Outside the US-ASCII repertoire, there are many more opportunities
+ for confusion; a complete set of guidelines is too lengthy to include
+ here. As long as names are limited to characters from a single
+ script, native writers of a given script or language will know best
+ when ambiguities can appear, and how they can be avoided. What may
+ look ambiguous to a stranger may be completely obvious to the average
+ native user. On the other hand, in some cases, the UCS contains
+ variants for compatibility reasons; for example, for typographic
+ purposes. These should be avoided wherever possible. Although there
+ may be exceptions, newly created resource names should generally be
+ in NFKC [UTR15] (which means that they are also in NFC).
+
+ As an example, the UCS contains the "fi" ligature at U+FB01 for
+ compatibility reasons. Wherever possible, IRIs should use the two
+ letters "f" and "i" rather than the "fi" ligature. An example where
+ the latter may be used is in the query part of an IRI for an explicit
+ search for a word written containing the "fi" ligature.
+
+ In certain cases, there is a chance that characters from different
+ scripts look the same. The best known example is the similarity of
+ the Latin "A", the Greek "Alpha", and the Cyrillic "A". To avoid
+ such cases, only IRIs should be created where all the characters in a
+ single component are used together in a given language. This usually
+ means that all of these characters will be from the same script, but
+ there are languages that mix characters from different scripts (such
+ as Japanese). This is similar to the heuristics used to distinguish
+ between letters and numbers in the examples above. Also, for Latin,
+ Greek, and Cyrillic, using lowercase letters results in fewer
+ ambiguities than using uppercase letters would.
+
+7.6. Display of URIs/IRIs
+
+ In situations where the rendering software is not expected to display
+ non-ASCII parts of the IRI correctly using the available layout and
+ font resources, these parts should be percent-encoded before being
+ displayed.
+
+ For display of Bidi IRIs, please see section 4.1.
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 35]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+7.7. Interpretation of URIs and IRIs
+
+ Software that interprets IRIs as the names of local resources should
+ accept IRIs in multiple forms and convert and match them with the
+ appropriate local resource names.
+
+ First, multiple representations include both IRIs in the native
+ character encoding of the protocol and also their URI counterparts.
+
+ Second, it may include URIs constructed based on character encodings
+ other than UTF-8. These URIs may be produced by user agents that do
+ not conform to this specification and that use legacy character
+ encodings to convert non-ASCII characters to URIs. Whether this is
+ necessary, and what character encodings to cover, depends on a number
+ of factors, such as the legacy character encodings used locally and
+ the distribution of various versions of user agents. For example,
+ software for Japanese may accept URIs in Shift_JIS and/or EUC-JP in
+ addition to UTF-8.
+
+ Third, it may include additional mappings to be more user-friendly
+ and robust against transmission errors. These would be similar to
+ how some servers currently treat URIs as case insensitive or perform
+ additional matching to account for spelling errors. For characters
+ beyond the US-ASCII repertoire, this may, for example, include
+ ignoring the accents on received IRIs or resource names. Please note
+ that such mappings, including case mappings, are language dependent.
+
+ It can be difficult to identify a resource unambiguously if too many
+ mappings are taken into consideration. However, percent-encoded and
+ not percent-encoded parts of IRIs can always be clearly
+ distinguished. Also, the regularity of UTF-8 (see [Duerst97]) makes
+ the potential for collisions lower than it may seem at first.
+
+7.8. Upgrading Strategy
+
+ Where this recommendation places further constraints on software for
+ which many instances are already deployed, it is important to
+ introduce upgrades carefully and to be aware of the various
+ interdependencies.
+
+ If IRIs cannot be interpreted correctly, they should not be created,
+ generated, or transported. This suggests that upgrading URI
+ interpreting software to accept IRIs should have highest priority.
+
+ On the other hand, a single IRI is interpreted only by a single or
+ very few interpreters that are known in advance, although it may be
+ entered and transported very widely.
+
+
+
+
+Duerst & Suignard Standards Track [Page 36]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ Therefore, IRIs benefit most from a broad upgrade of software to be
+ able to enter and transport IRIs. However, before an individual IRI
+ is published, care should be taken to upgrade the corresponding
+ interpreting software in order to cover the forms expected to be
+ received by various versions of entry and transport software.
+
+ The upgrade of generating software to generate IRIs instead of using
+ a local character encoding should happen only after the service is
+ upgraded to accept IRIs. Similarly, IRIs should only be generated
+ when the service accepts IRIs and the intervening infrastructure and
+ protocol is known to transport them safely.
+
+ Software converting from URIs to IRIs for display should be upgraded
+ only after upgraded entry software has been widely deployed to the
+ population that will see the displayed result.
+
+ Where there is a free choice of character encodings, it is often
+ possible to reduce the effort and dependencies for upgrading to IRIs
+ by using UTF-8 rather than another encoding. For example, when a new
+ file-based Web server is set up, using UTF-8 as the character
+ encoding for file names will make the transition to IRIs easier.
+ Likewise, when a new Web form is set up using UTF-8 as the character
+ encoding of the form page, the returned query URIs will use UTF-8 as
+ the character encoding (unless the user, for whatever reason, changes
+ the character encoding) and will therefore be compatible with IRIs.
+
+ These recommendations, when taken together, will allow for the
+ extension from URIs to IRIs in order to handle characters other than
+ US-ASCII while minimizing interoperability problems. For
+ considerations regarding the upgrade of URI scheme definitions, see
+ section 6.4.
+
+8. Security Considerations
+
+ The security considerations discussed in [RFC3986] also apply to
+ IRIs. In addition, the following issues require particular care for
+ IRIs.
+
+ Incorrect encoding or decoding can lead to security problems. In
+ particular, some UTF-8 decoders do not check against overlong byte
+ sequences. As an example, a "/" is encoded with the byte 0x2F both
+ in UTF-8 and in US-ASCII, but some UTF-8 decoders also wrongly
+ interpret the sequence 0xC0 0xAF as a "/". A sequence such as
+
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 37]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ "%C0%AF.." may pass some security tests and then be interpreted as
+ "/.." in a path if UTF-8 decoders are fault-tolerant, if conversion
+ and checking are not done in the right order, and/or if reserved
+ characters and unreserved characters are not clearly distinguished.
+
+ There are various ways in which "spoofing" can occur with IRIs.
+ "Spoofing" means that somebody may add a resource name that looks the
+ same or similar to the user, but that points to a different resource.
+ The added resource may pretend to be the real resource by looking
+ very similar but may contain all kinds of changes that may be
+ difficult to spot and that can cause all kinds of problems. Most
+ spoofing possibilities for IRIs are extensions of those for URIs.
+
+ Spoofing can occur for various reasons. First, a user's
+ normalization expectations or actual normalization when entering an
+ IRI or transcoding an IRI from a legacy character encoding do not
+ match the normalization used on the server side. Conceptually, this
+ is no different from the problems surrounding the use of
+ case-insensitive web servers. For example, a popular web page with a
+ mixed-case name ("http://big.example.com/PopularPage.html") might be
+ "spoofed" by someone who is able to create
+ "http://big.example.com/popularpage.html". However, the use of
+ unnormalized character sequences, and of additional mappings for user
+ convenience, may increase the chance for spoofing. Protocols and
+ servers that allow the creation of resources with names that are not
+ normalized are particularly vulnerable to such attacks. This is an
+ inherent security problem of the relevant protocol, server, or
+ resource and is not specific to IRIs, but it is mentioned here for
+ completeness.
+
+ Spoofing can occur in various IRI components, such as the domain name
+ part or a path part. For considerations specific to the domain name
+ part, see [RFC3491]. For the path part, administrators of sites that
+ allow independent users to create resources in the same sub area may
+ have to be careful to check for spoofing.
+
+ Spoofing can occur because in the UCS many characters look very
+ similar. Details are discussed in Section 7.5. Again, this is very
+ similar to spoofing possibilities on US-ASCII, e.g., using "br0ken"
+ or "1ame" URIs.
+
+ Spoofing can occur when URIs with percent-encodings based on various
+ character encodings are accepted to deal with older user agents. In
+ some cases, particularly for Latin-based resource names, this is
+ usually easy to detect because UTF-8-encoded names, when interpreted
+ and viewed as legacy character encodings, produce mostly garbage.
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 38]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ When concurrently used character encodings have a similar structure
+ but there are no characters that have exactly the same encoding,
+ detection is more difficult.
+
+ Spoofing can occur with bidirectional IRIs, if the restrictions in
+ section 4.2 are not followed. The same visual representation may be
+ interpreted as different logical representations, and vice versa. It
+ is also very important that a correct Unicode bidirectional
+ implementation be used.
+
+9. Acknowledgements
+
+ We would like to thank Larry Masinter for his work as coauthor of
+ many earlier versions of this document (draft-masinter-url-i18n-xx).
+
+ The discussion on the issue addressed here started a long time ago.
+ There was a thread in the HTML working group in August 1995 (under
+ the topic of "Globalizing URIs") and in the www-international mailing
+ list in July 1996 (under the topic of "Internationalization and
+ URLs"), and there were ad-hoc meetings at the Unicode conferences in
+ September 1995 and September 1997.
+
+ Many thanks go to Francois Yergeau, Matitiahu Allouche, Roy Fielding,
+ Tim Berners-Lee, Mark Davis, M.T. Carrasco Benitez, James Clark, Tim
+ Bray, Chris Wendt, Yaron Goland, Andrea Vine, Misha Wolf, Leslie
+ Daigle, Ted Hardie, Bill Fenner, Margaret Wasserman, Russ Housley,
+ Makoto MURATA, Steven Atkin, Ryan Stansifer, Tex Texin, Graham Klyne,
+ Bjoern Hoehrmann, Chris Lilley, Ian Jacobs, Adam Costello, Dan
+ Oscarson, Elliotte Rusty Harold, Mike J. Brown, Roy Badami, Jonathan
+ Rosenne, Asmus Freytag, Simon Josefsson, Carlos Viegas Damasio, Chris
+ Haynes, Walter Underwood, and many others for help with understanding
+ the issues and possible solutions, and with getting the details
+ right.
+
+ This document is a product of the Internationalization Working Group
+ (I18N WG) of the World Wide Web Consortium (W3C). Thanks to the
+ members of the W3C I18N Working Group and Interest Group for their
+ contributions and their work on [CharMod]. Thanks also go to the
+ members of many other W3C Working Groups for adopting IRIs, and to
+ the members of the Montreal IAB Workshop on Internationalization and
+ Localization for their review.
+
+
+
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 39]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+10. References
+
+10.1. Normative References
+
+ [ASCII] American National Standards Institute, "Coded
+ Character Set -- 7-bit American Standard Code for
+ Information Interchange", ANSI X3.4, 1986.
+
+ [ISO10646] International Organization for Standardization,
+ "ISO/IEC 10646:2003: Information Technology -
+ Universal Multiple-Octet Coded Character Set (UCS)",
+ ISO Standard 10646, December 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications
+ (IDNA)", RFC 3490, March 2003.
+
+ [RFC3491] Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep
+ Profile for Internationalized Domain Names (IDN)", RFC
+ 3491, March 2003.
+
+ [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", STD 63, RFC 3629, November 2003.
+
+ [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter,
+ "Uniform Resource Identifier (URI): Generic Syntax",
+ STD 66, RFC 3986, January 2005.
+
+ [UNI9] Davis, M., "The Bidirectional Algorithm", Unicode
+ Standard Annex #9, March 2004,
+ <http://www.unicode.org/reports/tr9/tr9-13.html>.
+
+ [UNIV4] The Unicode Consortium, "The Unicode Standard, Version
+ 4.0.1, defined by: The Unicode Standard, Version 4.0
+ (Reading, MA, Addison-Wesley, 2003. ISBN
+ 0-321-18578-1), as amended by Unicode 4.0.1
+ (http://www.unicode.org/versions/Unicode4.0.1/)",
+ March 2004.
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 40]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ [UTR15] Davis, M. and M. Duerst, "Unicode Normalization
+ Forms", Unicode Standard Annex #15, April 2003,
+ <http://www.unicode.org/unicode/reports/
+ tr15/tr15-23.html>.
+
+10.2. Informative References
+
+ [BidiEx] "Examples of bidirectional IRIs",
+ <http://www.w3.org/International/iri-edit/
+ BidiExamples>.
+
+ [CharMod] Duerst, M., Yergeau, F., Ishida, R., Wolf, M., and T.
+ Texin, "Character Model for the World Wide Web:
+ Resource Identifiers", World Wide Web Consortium
+ Candidate Recommendation, November 2004,
+ <http://www.w3.org/TR/charmod-resid>.
+
+ [Duerst97] Duerst, M., "The Properties and Promises of UTF-8",
+ Proc. 11th International Unicode Conference, San Jose
+ , September 1997,
+ <http://www.ifi.unizh.ch/mml/mduerst/papers/
+ PDF/IUC11-UTF-8.pdf>.
+
+ [Gettys] Gettys, J., "URI Model Consequences",
+ <http://www.w3.org/DesignIssues/ModelConsequences>.
+
+ [HTML4] Raggett, D., Le Hors, A., and I. Jacobs, "HTML 4.01
+ Specification", World Wide Web Consortium
+ Recommendation, December 1999,
+ <http://www.w3.org/TR/html401/appendix/
+ notes.html#h-B.2>.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet
+ Mail Extensions (MIME) Part One: Format of Internet
+ Message Bodies", RFC 2045, November 1996.
+
+ [RFC2130] Weider, C., Preston, C., Simonsen, K., Alvestrand, H.,
+ Atkinson, R., Crispin, M., and P. Svanberg, "The
+ Report of the IAB Character Set Workshop held 29
+ February - 1 March, 1996", RFC 2130, April 1997.
+
+ [RFC2141] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [RFC2192] Newman, C., "IMAP URL Scheme", RFC 2192, September
+ 1997.
+
+ [RFC2277] Alvestrand, H., "IETF Policy on Character Sets and
+ Languages", BCP 18, RFC 2277, January 1998.
+
+
+
+Duerst & Suignard Standards Track [Page 41]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ [RFC2368] Hoffman, P., Masinter, L., and J. Zawinski, "The
+ mailto URL scheme", RFC 2368, July 1998.
+
+ [RFC2384] Gellens, R., "POP URL Scheme", RFC 2384, August 1998.
+
+ [RFC2396] Berners-Lee, T., Fielding, R., and L. Masinter,
+ "Uniform Resource Identifiers (URI): Generic Syntax",
+ RFC 2396, August 1998.
+
+ [RFC2397] Masinter, L., "The "data" URL scheme", RFC 2397,
+ August 1998.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
+ Masinter, L., Leach, P., and T. Berners-Lee,
+ "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616,
+ June 1999.
+
+ [RFC2640] Curtin, B., "Internationalization of the File Transfer
+ Protocol", RFC 2640, July 1999.
+
+ [RFC2718] Masinter, L., Alvestrand, H., Zigmond, D., and R.
+ Petke, "Guidelines for new URL Schemes", RFC 2718,
+ November 1999.
+
+ [UNIXML] Duerst, M. and A. Freytag, "Unicode in XML and other
+ Markup Languages", Unicode Technical Report #20, World
+ Wide Web Consortium Note, June 2003,
+ <http://www.w3.org/TR/unicode-xml/>.
+
+ [XLink] DeRose, S., Maler, E., and D. Orchard, "XML Linking
+ Language (XLink) Version 1.0", World Wide Web
+ Consortium Recommendation, June 2001,
+ <http://www.w3.org/TR/xlink/#link-locators>.
+
+ [XML1] Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E.,
+ and F. Yergeau, "Extensible Markup Language (XML) 1.0
+ (Third Edition)", World Wide Web Consortium
+ Recommendation, February 2004,
+ <http://www.w3.org/TR/REC-xml#sec-external-ent>.
+
+ [XMLNamespace] Bray, T., Hollander, D., and A. Layman, "Namespaces in
+ XML", World Wide Web Consortium Recommendation,
+ January 1999, <http://www.w3.org/TR/REC-xml-names>.
+
+ [XMLSchema] Biron, P. and A. Malhotra, "XML Schema Part 2:
+ Datatypes", World Wide Web Consortium Recommendation,
+ May 2001, <http://www.w3.org/TR/xmlschema-2/#anyURI>.
+
+
+
+
+Duerst & Suignard Standards Track [Page 42]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ [XPointer] Grosso, P., Maler, E., Marsh, J. and N. Walsh,
+ "XPointer Framework", World Wide Web Consortium
+ Recommendation, March 2003,
+ <http://www.w3.org/TR/xptr-framework/#escaping>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 43]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+Appendix A. Design Alternatives
+
+ This section shortly summarizes major design alternatives and the
+ reasons for why they were not chosen.
+
+Appendix A.1. New Scheme(s)
+
+ Introducing new schemes (for example, httpi:, ftpi:,...) or a new
+ metascheme (e.g., i:, leading to URI/IRI prefixes such as i:http:,
+ i:ftp:,...) was proposed to make IRI-to-URI conversion scheme
+ dependent or to distinguish between percent-encodings resulting from
+ IRI-to-URI conversion and percent-encodings from legacy character
+ encodings.
+
+ New schemes are not needed to distinguish URIs from true IRIs (i.e.,
+ IRIs that contain non-ASCII characters). The benefit of being able
+ to detect the origin of percent-encodings is marginal, as UTF-8 can
+ be detected with very high reliability. Deploying new schemes is
+ extremely hard, so not requiring new schemes for IRIs makes
+ deployment of IRIs vastly easier. Making conversion scheme dependent
+ is highly inadvisable and would be encouraged by separate schemes for
+ IRIs. Using a uniform convention for conversion from IRIs to URIs
+ makes IRI implementation orthogonal to the introduction of actual new
+ schemes.
+
+Appendix A.2. Character Encodings Other Than UTF-8
+
+ At an early stage, UTF-7 was considered as an alternative to UTF-8
+ when IRIs are converted to URIs. UTF-7 would not have needed
+ percent-encoding and in most cases would have been shorter than
+ percent-encoded UTF-8.
+
+ Using UTF-8 avoids a double layering and overloading of the use of
+ the "+" character. UTF-8 is fully compatible with US-ASCII and has
+ therefore been recommended by the IETF, and is being used widely.
+
+ UTF-7 has never been used much and is now clearly being discouraged.
+ Requiring implementations to convert from UTF-8 to UTF-7 and back
+ would be an additional implementation burden.
+
+Appendix A.3. New Encoding Convention
+
+ Instead of using the existing percent-encoding convention of URIs,
+ which is based on octets, the idea was to create a new encoding
+ convention; for example, to use "%u" to introduce UCS code points.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 44]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+ Using the existing octet-based percent-encoding mechanism does not
+ need an upgrade of the URI syntax and does not need corresponding
+ server upgrades.
+
+Appendix A.4. Indicating Character Encodings in the URI/IRI
+
+ Some proposals suggested indicating the character encodings used in
+ an URI or IRI with some new syntactic convention in the URI itself,
+ similar to the "charset" parameter for e-mails and Web pages. As an
+ example, the label in square brackets in
+ "http://www.example.org/ros[iso-8859-1]&#xE9"; indicated that the
+ following "&#xE9"; had to be interpreted as iso-8859-1.
+
+ If UTF-8 is used exclusively, an upgrade to the URI syntax is not
+ needed. It avoids potentially multiple labels that have to be copied
+ correctly in all cases, even on the side of a bus or on a napkin,
+ leading to usability problems (and being prohibitively annoying).
+ Exclusively using UTF-8 also reduces transcoding errors and
+ confusion.
+
+Authors' Addresses
+
+ Martin Duerst (Note: Please write "Duerst" with u-umlaut wherever
+ possible, for example as "D&#252;rst" in XML and
+ HTML.)
+ World Wide Web Consortium
+ 5322 Endo
+ Fujisawa, Kanagawa 252-8520
+ Japan
+
+ Phone: +81 466 49 1170
+ Fax: +81 466 49 1171
+ EMail: duerst@w3.org
+ URI: http://www.w3.org/People/D%C3%BCrst/
+ (Note: This is the percent-encoded form of an IRI.)
+
+
+ Michel Suignard
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ U.S.A.
+
+ Phone: +1 425 882-8080
+ EMail: michelsu@microsoft.com
+ URI: http://www.suignard.com
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 45]
+
+RFC 3987 Internationalized Resource Identifiers January 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+Duerst & Suignard Standards Track [Page 46]
+
diff --git a/trunk/txt/vfs-ideas.txt b/trunk/txt/vfs-ideas.txt
new file mode 100644
index 00000000..7b41a064
--- /dev/null
+++ b/trunk/txt/vfs-ideas.txt
@@ -0,0 +1,425 @@
+Subject: Plans for gnome-vfs replacement
+
+Recently there has been a lot of discussions about the platform and
+the correct stacking order and quality of the modules. Gnome-vfs
+is a clear problem in this discussion. Having spent the last 4 years
+as the gnome-vfs maintainer, and even longer as the primary gnome-vfs
+user (in Nautilus) I'm well aware of the problems it has. I think that
+we've reached a point where the problems in the gnome-vfs architecture
+and its position in the stack are now ranking as one of the most
+problematic aspects of the gnome platform, especially considering the
+enhancements and quality improvements seen in other parts of the
+platform.
+
+So, I think the time has come for a serious look at what gnome-vfs
+could be. I've spent much time last week thinking about the weaknesses
+and problems of the current gnome-vfs and possibilities inherent in a
+redesign, both having learnt from 7 years of gnome-vfs existance and
+the improvements in the platform (both Gnome and surrounding
+technologies) since 1999 when it was designed.
+
+As soon as you spend some time looking at this problem is evident that
+to solve the platform ordering issues we really need a clean cut from
+the current gnome-vfs. I think the ideal level for a VFS would be in
+glib, in a separate library similar to gthread or gobject. That way
+gtk+ would be able to integrate with it and all gnome apps would have
+access to it, but it wouldn't affect small apps that just wants to use
+the glib core. Furthermore, not being libglib lets us use GObjects in
+the vfs, which means we can make a more modern API. Of course, this
+places quite some limitations on the vfs, especially in terms of
+dependencies and how integration with a UI should work.
+
+Any thoughs on the design of a vfs to replace gnome-vfs must be based
+on a solid understanding of the problems with the current system, to
+avoid redoing old mistakes and to make sure that we solve all the
+known problems of the current system. So, I'm gonna start by
+describing what I see as the main architectural and "hard" problems in
+gnome-vfs.
+
+The first, and most often discussed problem is of course
+compatibility. The various desktops use different vfs implementations,
+so they can't read each others files. Many applications use no VFS
+at all and have no way to access files on vfs shares. And the
+existence of multiple vfs implementations makes it unlikely that they
+will start using one.
+
+Gnome-vfs has no concept of Display Names, something which is very
+useful in a gui based system. In some places we auto-generate virtual
+desktop files to get this feature, but that is very hackish and need
+support in all apps to understand them. This is also quite closely
+related to handling filename charset encoding, another very weak point
+in gnome-vfs. The ideal way to reference a file is the actual real
+identifer on disk, database, remote share or what have you, as that
+can be passed between implementations, used with other access methods,
+etc. But to display something useful to the user you really need a
+user understandable utf-8 encoded string and a way to map that to/from
+the filename.
+
+There is no support for icons at the level of gnome-vfs. This means
+that all users above the vfs must implement it themselves (e.g. in
+nautilus and in the file selector). Each implementation have its own
+bugs, maintainance load and risk for different behaviour. It also
+means that vfs backends cannot supply their own icons, something which
+might be very useful for e.g. a network share based on some new fancy
+web service.
+
+The abstraction that gnome-vfs use is very similar to the posix model,
+which is problematic in several ways. The posix model matches poorly
+with the sort of highlevel operations that gnome applications wants to
+do with the vfs. The vfs is not typically used for what I would call
+"implementation files", which are things like configuration files,
+data files shipped with apps, system files, etc, but rather for what
+I'd like to call "user document files". These are the kind of files
+you open, save, or download from the internet to look at. Applications
+that use these would like highlevel operations that match the kind
+of operations you use on them, like read-entire-file, save-file,
+copy-file, etc.
+
+The posix model is also a bad match when implementing gnome-vfs
+modules. It requires some features from the implementation that can be
+difficult or impossible to implement. For example, its not really
+possible to support seeking when writing to a file on a webdav share,
+because a webdav put operation is essentially just streaming a copy of
+the new file contents. We currently work around this by locally
+caching all the file data being written and then sending it all in the
+close() call. This is clearly suboptimal for a lot of reasons, like
+applications not expecting close() to take a long time, and not
+checking its error conditions very closely.
+
+Another problem is that the posix model doesn't contain explicit
+operations for some of the things applications need to do. So instead
+applications rely on well known knowledge of the behaviour of posix
+to implement these operations. However, such behaviour might not be
+guaranteed on some gnome-vfs backends. A common example is the atomic
+save operation. A typical way to implement this on posix is to write
+to a temporary file in the same directory, and then rename over the
+target file, thus guaranteeing an atomic replacement of the file on
+disk, or a failure that didn't affect the original file. Of course,
+if a gnome-vfs application would use this and the backend was a
+webdav share to a subversion repository you would get some really
+weird versioning history in the repository for no good reason. If the
+backend had its own implementation of the save operation we could get
+both optimal behaviour on each backend, and an application API that
+doesn't require arcane knowledge of the atomicity of renames.
+
+One of the most problematic aspects of gnome-vfs is its authentication
+framework. The way it works is that you register callbacks to handle
+the authentication dialog, and whenever any operation needs to do
+authentication these callbacks will be called. The idea is that a
+console application would register a set of callbacks that print
+prompts on the console, and a Gtk+ application would have a set of
+callbacks that displays dialogs. There is a set of standard dialog
+based callbacks in libgnomeui that you can install by calling
+gnome_authentication_manager_init(). From an initial look this seems
+like a reasonable approach, but it turns out that this creates a host
+of different problems.
+
+One problem is how you connect this to the application. A lot of
+people are unaware that you have to call gnome_auth_manager_init() to
+get authentication dialogs, or don't want to depend on libgnomeui to
+do so. So a lot of applications don't work with authentication. Those
+who do call it generally have pretty poor integration with the
+authentication dialogs. For instance, the general authentication
+dialogs can't be marked as parents of whatever dialog caused the
+authentication (because they have know whay of knowing what caused
+it), and all sorts of problems appear when there is a modal dialog
+displayed already.
+
+Another problem is the combination of blocking gnome-vfs calls and
+authentication. When calling a blocking operation like read() and it
+results in a password dialog we have to start up a recursive mainloop
+to display it. Not only is this unexpected for the application, it
+also brings with it all the type of reentrancy issues that we had in
+bonobo. Even worse, there is no way to make this threadsafe. To make
+it threadsafe the callback would have to take the gdk lock before
+doing any Gtk+ calls, but this would cause a deadlock if the
+application called it with the gdk lock held. If we don't take the
+gdk lock then you can't do blocking vfs calls on any thread but the
+mainloop, or you have to take the gdk lock on any gnome-vfs call.
+
+The authentication callbacks can appear at *any* gnome-vfs entry
+point, which makes it very hard to write gnome-vfs applications that
+don't accidentally trigger a lot of authentication dialogs. For
+instance, the tree sidebar in nautilus has to take particular care not
+to stat or otherwise look at the toplevel items until the user
+explicitly expands them, otherwise you'd get authentication dialogs
+every time you opened a window. Its also easy to get multiple
+authentication dialogs for the same entity.
+
+The way threads are used in gnome-vfs is problematic, both from the
+point of view of writing backends, and for users of the library. For
+users it forces the use of threading, even if the application doesn't
+use the asynchronous calls that use the threading. It also enforces
+the need for a gnome_vfs_init() function, as thread initialization
+must be done very early.
+
+For backend implementations the use of threads forces every
+backend to be threadsafe. Many of the backends are inherently single
+threaded, either because they use non-threadsafe libraries like the
+smb backend, or because the server being wrapped forces serialized
+access (like an ftp backend where you really only want one connection
+to the server).
+
+Backends run in context of the application using gnome-vfs, which can
+be a gtk+ app, but as well a console application, so they have no
+control or guarantee of their environment. For instance, they cannot
+rely on the existance of a mainloop, so there is no way to use
+e.g. timeouts to handle invalidation of caches. One way we have tried
+to solve this is to move some backends to the gnome-vfs daemon, where
+they can rely on the existance of the mainloop.
+
+Gnome-vfs use something called "gnome vfs uris" to identify
+files. These are similar, but not entierly identical to the types of
+uri used in webbrowsers. For instance, we often make us our own types
+of URIs when there is no official standard for them (although such
+standards might appear later, with incompatible behaviour). We also
+have a "well defined" posix-like type of behaviour that isn't the same
+as for web uris. The most extreme example would be mailto:, but even
+things like ftp:// uris are different. The ftp uri rfc explains how
+ftp:///dir/file.txt refers to $(login_dir)/dir/file.txt, and that you
+have to use ftp:///%2fdir/file.txt to refer to the absolute path
+/dir/file.txt on the server. Clearly we can't have pathname handling
+semantics that vary depending on the backend (no app would get it
+right), so we ignore the rfcs on this.
+
+Then there is the thing with escaping and unescaping uris. Although
+technically not very complex it is just are very hard to get right all
+the time. Among the most common questions on the gnome-vfs list is
+what the various escape/unescape functions does, what arguments has to
+be escaped, and how to display uris "nicely" (i.e. without escapes,
+although that makes them invalid uris). This is made extra complicated
+due to the poor handling of filename encodings and display names, and
+the fact that only "less common" cases (like spaces in filenames)
+break if you get it wrong.
+
+Last but not least, the fact that gnome-vfs uses something called a
+"uri" gives people the wrong impression of what the library is
+designed for. It causes people to complain when it doesn't have some
+support for mailto: links, and it makes people want support for
+cookies, extra http headers and other things typically used by a web
+browser. This isn't really the kind of use that vfs is targeted at. A
+library specific to that sort use would probably fit these apps much
+better.
+
+Most gnome-vfs state is tied to the application that uses it, which I
+think is quite unexpected by the user. For instance, when you log into
+a network share in nautilus and then click on a file to open it, the
+opening application will have to re-connect and re-authenticate to
+the share, much to the users surprise. I really think most people
+expect a login like that is somehow session global. We do sometimes
+misuse gnome-keyring to "solve" the authentication issue, but even
+then we still have multiple connections to the network share, which
+can cause problem, for instance with ftp shares that use round-robin
+dns where the mirrors aren't fully sync:ed up. Again, some backends
+(smb) are now in the daemon which solves this issue.
+
+gnome_vfs_xfer() is possibly the worst-API call in the whole gnome
+platform. Its a single, buggy, do-it-all function with shitloads of
+combinations of flags and arguments to do all sort of things, with
+little or no semantic specifications or testcases. Its also to a large
+extent unnecessary for most applications and could easily be part of
+the file manager instead of a generic library. I'm also not sure that
+the "first do preflight calculation, then execute operation" model it
+uses is right. It is inherently racy, since the target or source could
+easily change during the preflight, and it makes error reporting and
+handling much more complicated.
+
+The behaviour of symlink resolution in the UI has been discussed many
+times. Should clicking on a symlink "foo" in $dir go to $dir/foo or to
+the target directory. The Nautilus maintainers has decided that the
+best way to approach this is to have symlinks be used for "filesystem
+implementation" (like a symlink for /home -> /mnt/hdb2) and thus not
+be resolved on activation. However, we should (this hasn't been
+finished yet) support a different form of links (called "shortcuts" in
+the UI) that always resolve on activation. At the moment there is no
+support for anything like that in gnome-vfs, so we abuse desktop files
+for this. We even generate virtual in-memory desktop files in the smb
+backend to get this behaviour. Proper support for shortcuts in the
+vfs API would let apps automatically work without ugly desktop file
+hacks.
+
+Over the years gnome-vfs has accumulated a lot of cruft. It links to a
+lot of libraries, including openssl, gconf+ORBit2, avahi, dbus, popt,
+libxml, kerberos, libz and libresolv. Very few applications need all
+of these, yet every application that uses gnome-vfs links to all of
+them. Furthermore, some of the functionallity in gnome-vfs, like the
+wrapper for dns-sd, resolving, network utilities, ls parsing
+functions, ssl support, pty handling are perhaps not best suited for a
+vfs library, nor do they always have great apis and quality
+implementations. We could definately clean this up and minimize the
+APIs.
+
+At some point in time gnome_vfs_uri_is_local() started detecting and
+returning TRUE for NFS mounts and other type of local network
+mounts. This is both slow and unexpected, and has led to problems and
+unnecessary changes in many places.
+
+The way the cancellation API for asynchronous operations is set up
+creates races and fragile code. The main issue is that if you call
+cancel before the operation callback has been called the callback will
+not be called. However, the callback typically wants to free some sort
+of user_data object passed to it, so that has to be handled also when
+you call cancellation. Couple this with the fact that there is no
+destroy notifies and you can't cancel after the operation callback has
+been called and you get an extremely tricky setup of combined
+callbacks. Furthermore, if threads are used there are some inherent
+races wrt detecting if the callback has been called when cancel is
+called, making it essentially impossible to get this right.
+
+There are also a bunch of issues with the current gnome-vfs that could
+technically be fixed like support for hidden file flags,
+backend-extensible metadata, no standard vfs dialogs like progress
+bars, etc.
+
+Last week I started thinking about a new design for a gnome-vfs
+replacement that would solve most of these issues, and at the same
+time gives a correct ordering of the platform stack. I've come up with
+a highlevel architecture that I think will work, even though I haven't
+yet finished it in detail or gotten the API totally worked out. Its
+somewhat of a radical departure from gnome-vfs as it is today, so
+brace with me as I try to explain the model and the ideas behind it.
+
+The gnome-vfs model is what I would call stateless. You can at any
+time throw a URI at it and it will do everything required to access
+the location. There is no need to, nor is there a way to set up
+anything like a "session" with a remote share. Of course, in practice
+this is not the way network shares work, so all sorts of session
+initiation, caching and other magic happens under the covers to make
+it look stateless. This is the source of all the problems with the
+gnome-vfs authentication model.
+
+I'd like to propose using a stateful model, where you have to
+explicitly initiate a session ("mount" a share) before you can start
+accessing files. This will give a well specified time when all forms
+of authentication will happen, when applications expect it and when
+they can use a more expressive and suitable API for this kind of
+operation. The actual i/o operations will then never cause any sort of
+authentication issues, and can thus be purely non-graphical
+(i.e. glib-only apps can do i/o). I imagine all/most actual mounting
+of shares will happen in the file manager and the file selector, or at
+gnome-session startup, so applications don't really need to handle
+this themselves.
+
+Not only is the model stateful. I'd like all state to be session
+global. That is, all mounts and network connections are shared between
+all applications in the session. So, if you pass a file reference from
+one app to another there is no need to log in again or anything like
+that. I think this is what users expect.
+
+Having a global stateful model means all non-local vfs accesses go
+through the vfs daemon. This works pretty well with the smb backend in
+the current gnome-vfs, and smb is the backend most likely to have high
+bandwidth traffic, so this doesn't seem to be a large performance
+problem. Although we do have to take the performance aspect into
+consideration when designing the daemon.
+
+In order to avoid all the problems with threading described above the
+vfs daemon will not use threads. In fact, I think the best approach is
+to let each active mountpoint be its own process. That way we get
+robustness (one mount can't crash the others) and simplify the backend
+creation greatly (each backend fully controls its context). It also
+will let us do concurrent access to e.g. two smb shares (like a copy
+from one to the other). We can't really do this atm since the thread
+lock in the smb backend serializes such access. But with two smb
+processes this is not a problem.
+
+There might be an issue with using separate processes for the
+mountpoints bloating up the desktop, but I don't think that it will be
+much of a problem. None of these processes will use the gui libraries
+that are the real sources of unshared dirty memory use. I tried a
+simple process that just used gobject and ran a mainloop. It only used
+78k of dirty memory. Also, each server need only link to and
+initialize the few libraries it needs, further keeping memory use down
+and avoiding bloat in all applications (e.g. apps need not link to
+openssl).
+
+As a consequence of the stateful model we don't need the stateless
+properties that URIs has as identifier. To avoid all the problems
+comming from the use of URIs we use a much simpler form of
+identifier. Namely filenames, in a hierarchical tree with
+mountpoints. These filenames are from an extended set of strings that
+includes the set of normal filenames, but also includes some platform
+dependent extensions. On win32 the full set might be some form of
+stringified version of the ITEMIDLIST from the windows shell api, and
+on unix we would use some out of band prefix to mark a non-local
+filename.
+
+For example, we could be to use "//.network/" as a prefix for the vfs
+filename namespace. A smb share might then be accessed as
+"//.network/smb/computer:share/dir/file.txt", or a ftp share as
+"//.network/ftp/alex@ftp.gnome.org/dir/file.txt". With a setup like
+"//.network/$method/$mount_object/" it would be quite easy to find the
+process handling the mount. Just ask for a dbus named object like
+"org.glib.gvsf.smb.computer:share". It is also very easy to detect
+local filenames and short-circuit to in-process i/o.
+
+These filenames would be the real identifier for the files, and as
+such not really presentable to the user as it. You'd need to ask for
+the display name via the vfs to get a user readable utf8-encoded
+string for display.
+
+The set of operations on files and folders would be both simplified
+and extended. We'd remove complicated things like read+write access to
+a file, and give less posix-like guarantees. We also make seek and
+truncate support optional in the backend. But then we will extend the
+set of operations possible to allow things like copy on the remote
+side (to avoid a download+upload operation on copy) and to have
+a set of highlevel operations that applications want, like "save" that
+implements the best way to save for each particular backend.
+
+We support metadata like display name, mimetypes, icon, and some
+general information like length and mtime. But we make support for
+getting the full "struct stat" buffer backend optional, as that isn't
+a good abstraction for most backends. Also, the API will be designed
+on the idea that network latency is expensive, so that there will only
+be one call to stat() or readdir() needed to read all the metadata
+requested by the application. (Whereas posix will have readdir return
+only the names and force you to stat each file in a separate
+roundtrip.)
+
+We likely don't want the full gnome/unix vfs implementation in
+glib, instead glib will only ship an implementation of the vfs API for
+local file access, and one that communicates to the vfs
+daemon(s). Then we ship the daemon and the implementations of the
+various backends externally.
+
+We will also write a single gnome-vfs backend that allows access to
+all the glib vfs shares by using a uri like gvfs:///XXX that just maps
+to //.network/XXX. We can also implement a similar backend for kio so
+that kde applications can read and write to the shares.
+
+Furthermore, if FUSE is supported on the system we can write a FUSE
+filesystem so that we can access the files as $HOME/.network/XXX. This
+can be made extra nice if the application (like e.g. acrobat) uses
+the gtk+ file selector but not the vfs by having the file selector
+detect a filename like this and reverse-mapping it into a vfs pathname
+and use the vfs for folder access.
+
+I've been doing some initial sketching of the glib API, and I've
+started by introducing base GInputStream and GOutputStream similar to
+the stream objects in Java and .Net. These have async i/o support and
+will make the API for reading and writing files nicer and more
+modern. There is also a GSeekable interface that streams can
+optionally implement if they support seeking.
+
+I've also introduced a GFile object that wraps a file path. This means
+you don't have to do tedious string operations on the pathnames to
+navigate the filesystem. It also means we can use the openat() class
+of file operations when traversing the filesystem tree, avoiding some
+forms of races when we do things like recursive copies.
+
+To support the stateful model and still have some form of caching we
+will also need to add some cache specific api so that you can trigger
+a reload of information from a directory. Otherwise a reload operation
+in the file manager wouldn't always get the latest state on something
+like a ftp share where we cache things aggressively.
+
+I have some initial code here for some of the basic APIs, but its far
+from finished and I'd like to spend some more time working on it
+before I present it. However, I think the general architecture is
+pretty sound and in a state where it can be discussed.
+
+Hopefully this description of my plans is enought to make people
+understand some of my ideas and allow us to start and discussion about
+the future of gnome-vfs. Also, consider it a heads up that I and other
+people will likely be working on this this in the future.
diff --git a/trunk/txt/vfs-names.txt b/trunk/txt/vfs-names.txt
new file mode 100644
index 00000000..25833d7c
--- /dev/null
+++ b/trunk/txt/vfs-names.txt
@@ -0,0 +1,142 @@
+Local filenames (in utf8 mode)
+1) standard: /etc/passwd
+2) utf8 and spaces: "/tmp/a åäö.txt" (encoding==utf8)
+3) latin-1 and spaces: "/tmp/a åäö.txt" (encoding==iso8859-1)
+4) filename without encoding: "/tmp/bad:\001\010\011\012\013" (as a C string)
+5) mountpoint: /mnt/cdrom (cd has title "CD Title")
+
+Ftp mount to ftp.gnome.org
+(where filenames are stored as utf8, this is detected by using
+ ftp protocol extensions (there is an rfc) or by having the user
+ specify the encoding at mount time)
+
+6) normal dir: /pub/sources
+7) valid utf8 name: /dir/a file öää.txt
+8) latin-1 name: /dir/a file öää.txt
+
+Ftp mount to ftp.gnome.org (with filenames in latin-1)
+9) latin-1 name: /dir/a file öää.txt
+
+backend that stores display name separate from real name. Examples
+could be a flickr backend, a file backend that handles desktop files,
+or a virtual location like computer:// (which is implemented using
+virtual desktop files atm).
+
+10) /tmp/foo.desktop (with Name[en]="Display Name")
+
+special cases:
+ftp names relative to login dir
+
+Places where display filenames (i.e utf-8 strings) are used:
+
+A) Absolute filename, for editing (nautilus text entry, file selector entry)
+B) Semi-Absolute filename, for display (nautilus window title)
+C) Relative file name, for display (in nautilus/file selector icon/list view)
+D) Relative file name, for editing (rename in nautilus)
+E) Relative file name, for creating absolute name (filename completion for a)
+ This needs to know the exact form of the parent (i.e. it differs for filename vs uri).
+ I won't list this below as its always the same as A from the last slash to the end.
+
+This is how these work with gnome-vfs uris:
+
+ A B C D
+1) file:///etc/passwd passwd passwd passwd
+2) file:///tmp/a%20%C3%B6%C3%A4%C3%A4.txt a åäö.txt a åäö.txt a åäö.txt
+3) file:///tmp/a%20%E5%E4%F6.txt a ???.txt a ???.txt (invalid unicode) a ???.txt
+4) file:///tmp/bad%3A%01%08%09%0A%0B bad:????? bad:????? (invalid unicode) bad:?????
+5) file:///mnt/cdrom CD Title (cdrom) CD Title (cdrom) CD Title
+6) ftp://ftp.gnome.org/pub/sources sources on ftp.gnome.org sources sources
+7) ftp://ftp.gnome.org/dir/a%20%C3%B6%C3%A4%C3%A4.txt a åäö.txt on ftp.gnome.org a åäö.txt a åäö.txt
+8) ftp://ftp.gnome.org/dir/a%20%E5%E4%F6.txt a ???.txt on ftp.gnome.org a ???.txt (invalid unicode) a ???.txt
+9) ftp://ftp.gnome.org/dir/a%20%E5%E4%F6.txt a åäö.txt on ftp.gnome.org a åäö.txt a åäö.txt
+10)file:///tmp/foo.desktop Display Name Display Name Display Name
+
+The stuff in column A is pretty insane. It works fine as an identifier
+for the computer to use, but nobody would want to have to type that in
+or look at that all the time. That is why Nautilus also allows
+entering some filenames as absolute unix pathnames, although not all
+filenames can be specified this way. If used when possible the column
+looks like this:
+
+ A
+1) /etc/passwd
+2) /tmp/a åäö.txt
+3) file:///tmp/a%20%E5%E4%F6.txt
+4) file:///tmp/bad%3A%01%08%09%0A%0B
+5) /mnt/cdrom
+6) ftp://ftp.gnome.org/pub/sources
+7) ftp://ftp.gnome.org/dir/a%20%C3%B6%C3%A4%C3%A4.txt
+8) ftp://ftp.gnome.org/dir/a%20%E5%E4%F6.txt
+9) ftp://ftp.gnome.org/dir/a%20%E5%E4%F6.txt
+10)/tmp/foo.desktop
+
+As we see this helps for most normal local paths, but it becomes
+problematic when the filenames are in the wrong encoding. For
+non-local files it doesn't help at all. We still have to look at these
+horrible escapes, even when we know the encoding of the filename.
+
+The examples 7-9 in this version shows the problem with URIs. Suppose
+we allowed an invalid URI like "ftp://ftp.gnome.org/dir/a åäö.txt"
+(utf8-encoded string). Given the state inherent in the mountpoint we
+know what encoding is used for the ftp server, so if someone types it
+in we know which file they mean. However, suppose someone pastes a URI
+like that into firefox, or mails it to someone, now we can't
+reconstruct the real valid URI anymore. If you drag and drop it
+however, the code can send the real valid uri so that firefox can load
+it correctly.
+
+So, this introduces two kinds of of URIs that are "mostly similar" but
+breaks in many nonobvious cases. This is very unfortunate, imho not
+acceptable. I think its ok to accept a URI typed in like
+"ftp://ftp.gnome.org/dir/a åäö.txt" and convert it to the right uri,
+but its not right to display such a uri in the nautilus location bar,
+as that can result in that invalid uri getting into other places.
+
+Since I dislike showing invalid URIs in the UI I think it makes sense
+to create a new absolute pathname display and entry format. Ideally
+such a system should allow any ascii or utf8 local filename to be
+represented as itself. Furthermore it would allow input of URIs, but
+immediately convert them to the display format (similar to how
+inputing a file:// uri in nautilus displays as a normal filename).
+
+One solution would be to use some other prefix than / for
+non-local files, and to use some form of escaping only for non-utf8
+chars and non-printables. Here is an example:
+
+ A
+1) /etc/passwd
+2) /tmp/a åäö.txt
+3) /tmp/a \xE5\xE4\xF6.txt
+4) /tmp/bad:\x01\x08\x09\x0A\x0B
+5) /mnt/cdrom
+6) :ftp:ftp.gnome.org/pub/sources
+7) :ftp:ftp.gnome.org/dir/a åäö.txt
+8) :ftp:ftp.gnome.org/dir/a \xE5\xE4\xF6.txt
+9) :ftp:ftp.gnome.org/dir/a åäö.txt
+10)/tmp/foo.desktop
+
+Under the hood this would use proper, valid escaped URIs. However, we
+would display things in the UI that made some sense to users, only
+falling back to escaping in the last possible case.
+
+The API could look something like:
+
+GFile *g_file_new_from_filename (char *filename);
+GFile *g_file_new_from_uri (char *uri);
+GFile *g_file_parse_display_name (char *display_name);
+
+Another approach (mentioned by Jürg Billeter on irc yesterday) is to
+move from a pure textual representation of the full uri to a more
+structured UI. For example the ftp://ftp.gnome.org/ part of the URI
+could be converted to a single item in the entry looking like
+[#ftp.gnome.org] (where # is an ftp icon). Then the rest of the entry
+would edit just the path on the ftp server, as a local filename. The
+disadvantage here is that its a bit harder to know how to type in a
+full pathname including what method to use and what server (you'd type
+in a URI). This isn't necessarily a huge problem if you rarely type in
+remote URIs (instead you can follow links, browse the network, add
+favourites, etc).
+
+I don't know how hard this is to do from a Gtk+ perspective
+though. Its somewhat similar to what the evolution address entry does.
+